Wednesday, January 4, 2017

Android2

Can we change application name in after deployment?

Things That Cannot Change:
The most obvious and visible of these is the “manifest package name,” the unique name you give to your application in its AndroidManifest.xml. The name uses a Java-language-style naming convention, with Internet domain ownership helping to avoid name collisions. For example, since Google owns the domain “google.com”, the manifest package names of all of our applications should start with “com.google.” It’s important for developers to follow this convention in order to avoid conflicts with other developers.
Once you publish your application under its manifest package name, this is the unique identity of the application forever more. Switching to a different name results in an entirely new application, one that can’t be installed as an update to the existing application.


How do you handle the disfuntion in ScreenOrientation ?

Solution 1 – Think twice if you really need an AsyncTask.
AsyncTasks are good for performing background work, but they are bound to the Activity which adds some complexity. For things like making HTTP requests to a server perhaps you should consider an IntentService. IntentService used in conjunction with a BroadcastReceiver or ResultReceiver to deliver results, could do a better job than an AsyncTask in certain situations.
Solution 2 – Put the AsyncTask in a Fragment.
Using fragments probably is the cleanest way to handle configuration changes. By default, Android destroys and recreates the fragments just like activities, however, fragments have the ability to retain their instances, simply by calling: setRetainInstance(true), in one of its callback methods, for example in the onCreate().
There’s however one aspect that should be taken in consideration in order to achieve the desired result. Our AsyncTask uses a ProgressDialog to signal when the AsyncTask is started, and dismisses it when the task is done. This complicates a bit the things because even if we are using setRetainInstance(true), we should close all windows and dialogs when the Activity is destroyed, otherwise we will get an: Activity has leaked window com.android.internal.policy…  exception. This happens when you try to show a dialog after you have exited the Activity.
In order to address this issue, we will add some logic to keep track of AsyncTask status (running/not running). We will dismiss the ProgressDialog when the fragment is detached from activity, and check in onActivityCreated() the status of AsyncTask. If the status is “running”, this means we are returning from a screen orientation and we will just re-create and display the ProgressDialog to show that the AsyncTask is still working.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class ExampleFragment extends Fragment implements TaskListener, OnClickListener {
 
    private ProgressDialog progressDialog;
    private boolean isTaskRunning = false;
    private AsyncTaskExample asyncTask;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }
 
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // If we are returning here from a screen orientation
        // and the AsyncTask is still working, re-create and display the
        // progress dialog.
        if (isTaskRunning) {
            progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait a moment!");
        }
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);
        Button button = (Button) view.findViewById(R.id.start);
        button.setOnClickListener(this);
        return view;
    }
 
    @Override
    public void onClick(View v) {
        if (!isTaskRunning) {
            asyncTask = new AsyncTaskExample(this);
            asyncTask.execute();
        }
    }
 
    @Override
    public void onTaskStarted() {
        isTaskRunning = true;
        progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait a moment!");
    }
 
    @Override
    public void onTaskFinished(String result) {
        if (progressDialog != null) {
            progressDialog.dismiss();
        }
        isTaskRunning = false;
    }
 
    @Override
    public void onDetach() {
        // All dialogs should be closed before leaving the activity in order to avoid
        // the: Activity has leaked window com.android.internal.policy... exception
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
        super.onDetach();
    }
}
Solution 3 – Lock the screen orientation
You could do this in 2 ways:
a) permanently locking the screen orientation of the activity, specifying the screenOrientation attribute in the AndroidManifest with “portrait” or “landscape” values:
1
2
3
<activity
   android:screenOrientation="portrait"
   ...  />
b) or, temporarily locking the screen in onPreExecute(), and unlocking it in onPostExecute(), thus preventing any orientation change while the AsyncTask is working:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
public void onTaskStarted() {
    lockScreenOrientation();
    progressDialog = ProgressDialog.show(CopyOfCopyOfMainActivity.this, "Loading", "Please wait a moment!");
}
 
@Override
public void onTaskFinished(String result) {
    if (progressDialog != null) {
        progressDialog.dismiss();
    }
    unlockScreenOrientation();
}
 
private void lockScreenOrientation() {
    int currentOrientation = getResources().getConfiguration().orientation;
    if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}
 
private void unlockScreenOrientation() {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
Solution 4 – Prevent the Activity from being recreated.
This is the easiest way to handle configuration changes, but the less advised. The only thing you need to do is to specify the configChanges attribute followed by a list of values that specifies when the activity should prevent itself from restarting.
1
2
3
4
<activity
   android:configChanges="orientation|keyboardHidden"
   android:name=".MainActivity"
   .... />
Using this approach however, is not recommended, and this is clearly stated in the Android documentation: Using this attribute should be avoided and used only as a last-resort.
You may ask what’s wrong with this approach. Well, if you build the above example against Android 2.2 it will work fine, but if you build it against Android 3.0 and higher, you may notice that the application still crashes on orientation change. This is because starting  with Android 3.0 you need also to handle the screenSize, and smallestScreenSize:
1
2
3
4
<activity
   android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"
   android:name=".MainActivity"
   .... />
As it turns out, not only a screen orientation causes the Activity to recreate, there are also other events which may produce configuration changes and restart the Activity, and there’s a good chance that we won’t handle them all. This is why the use of this technique is discouraged.

0 comments:

Post a Comment