An in-depth analysis of the implementation points of application and handover in Android system _android

Source: Internet
Author: User
Tags stub

Before introducing the program implementation, let's look at the basics of activities and tasks in Android.
As we all know, one activity can start another, even if it is defined in a different application, for example, if you want to show the user a map of information, there is already a task that can do this, So now all your activity needs to do is put the request information into a intent object and pass the intent object to StartActivity (), and the map can be displayed, but after the user presses the Back button, Your activity again appears on the screen.

For users, showing the activity of the map and your activity seems to be in an application, although they are defined in other applications and run in that process. Android puts your activity and borrowed activity into a task to maintain the user experience. Then the task is organized into a stack of interrelated activity, and the activity at the bottom of the stack is the task, usually the activity the user chooses in the Application Launcher. The activity at the top of the stack is one that is currently running activity--the user is interacting with.

When an activity initiates another activity, the newly initiated activity is pressed into the stack as a running activity. The old activity is still on the stack. When the user presses the back key, the running activity pop-up stack, the old activity resumes as the running activity. The stack contains objects, so if multiple objects of the same activity subclass are opened in a task-for example, multiple map browsers-the stack has a separate entry for each instance. The activity in the stack is not reordered and will only be ejected. A task is a stack of activity instances, not a class or element in a manifest file, so it is not possible to set the attributes of a task regardless of its activity, and all the attribute values of a task are set in the activity at the bottom. This is required for affinity. About affinity no longer detailed here, you can query the document.

All the activity in a task works as a whole. The entire task (the entire activity stack) can be pushed to the foreground or pushed to the background. Suppose that there are three activity under a running task in which four activity--are running, when the user presses the home key, returns to the program launcher and runs the new application (actually running a new task), Then the current task is back in the background, and the root activity of the newly opened application is displayed, and after a while the user returns to the application and then selects the previous application (the prior task), the previous task is back at the front. , when the user presses the back key, the screen does not show the activity of the newly opened application that has just left, but is the activity at the top of the task stack, which is returned to the foreground, to show the next activity of the task. These are activities and task-general behavior, but almost all aspects of this behavior can be modified. The relationship between activity and task, and the behavior of activities in a task, is influenced by the identity of the intent object that initiates the action and the attributes of the <Activity> element in the manifest file.

The above is a description of the activity and task.

In the development of Android projects, users will inevitably do program switching, in the process, the program will go into the background to run, need to use the Task Manager or click the program or by clicking the icon in the message to return to the original interface. This effect is similar to the effect of Tencent QQ, open QQ after showing the main interface, in the use of other programs, QQ will be in the form of icons displayed in the Information Notice bar, if the use of QQ and then click on the Information Notice bar icon display QQ main interface.
Let's take a look at this example to implement the effect chart:

In the second figure in the figure above, we will return to the original activity when we click.

When our program goes backstage, it appears as an icon in the top of our emulator, as shown in the following figure:

The general practice for this effect is to write the appropriate code in the OnStop () method in the activity, because the OnStop () method is invoked when the activity enters the background, and we can OnStop () Method displays the program icon and information in notification form, where the code looks like this:

@Override 
  protected void OnStop () { 
  //TODO auto-generated method Stub 
  super.onstop (); 
  LOG.V ("BACKGROUND", "program into the Background"); 
  Shownotification (); 
  } 

The above Shownotification () method is notification.
Then click on the notification of the information notification bar and return to the original activity.
Of course, we can also capture the home key, which displays notification when the user presses the home key, and here's the code example:

Click the Home button to run the program into 
 
  the background @Override public 
 
  boolean onKeyDown (int keycode, keyevent event) { 
 
    //TODO auto-generated method Stub 
 
    //press Home key 
 
    if (keycode = = keyevent.keycode_home) { 
 
      //Show Notification 
 
      notification = new Notificationextend (this); 
 
      Notification.shownotification (); 
 
      Movetasktoback (true);         

      return true; 
 
    } 
 
    Return Super.onkeydown (KeyCode, event); 
 
  } 

The notificationextend here is an encapsulation of the display notification, and the code in the class is as follows:

Package com.test.background; 
 
Import android.app.Activity; 
 
Import android.app.Notification; 
 
Import Android.app.NotificationManager; 
 
Import android.app.PendingIntent; 
 
Import android.content.Intent; 

Import Android.graphics.Color; /** * Notification Extended class * @Description: Notification Extension class * @File: Notificationextend.java * @Package Com.test.backgro 

  und * * Public class Notificationextend {private activity context; Public Notificationextend {//TODO auto-generated constructor stub this.context = Context 
 
  ; }//Show notification public void Shownotification () {//Create a Notificationmanager reference Notificationman Ager Notificationmanager = (Notificationmanager) context.getsystemservice (android.content.Conte Xt. 
 
    Notification_service);  
 
        Defines the various properties of Notification Notification Notification = new Notification (R.drawable.icon, "reader", System.currenttimemillIs ()); 
 
    Place this notice in the "ongoing", the "Running" group, in the notification bar notification.flags |= notification.flag_ongoing_event; 
 
    Indicates that this notification is automatically cleared after clicking "Purge Notification" in the notification bar. 
 
    Notification.flags |= notification.flag_auto_cancel notification.flags |= notification.flag_show_lights; 
 
    Notification.defaults = notification.default_lights; 
 
    Notification.ledargb = Color.Blue; 

    NOTIFICATION.LEDONMS = 5000; Set the event message for the notification charsequence contenttitle = "Reader display information"; Notification Bar title Charsequence ContentText = "Push message display, see ..."; 
 
    Notification bar content Intent notificationintent = new Intent (Context,context.getclass ()); 
    Notificationintent.setaction (Intent.action_main); 
    Notificationintent.addcategory (Intent.category_launcher); Pendingintent contentintent = pendingintent.getactivity (context, 0, NOTIFICATIONINTENT,PENDINGINTENT.FLAG_UPDATE_CU 
    Rrent); 
    Notification.setlatesteventinfo (context, Contenttitle, ContentText, contentintent); Pass the notification to Notificationmanag.Er notificationmanager.notify (0, notification); //Cancel notification public void Cancelnotification () {Notificationmanager Notificationmanager = (notific 
 
    Ationmanager) Context.getsystemservice (Android.content.Context.NOTIFICATION_SERVICE); 
 
  Notificationmanager.cancel (0); 

 } 
 
}

There is a need to set up each activity in the configuration file to run on a single task, otherwise each return to the original will add a new one, not return to the original.

A phenomenon that does not return to the original activity occurs when the Flag_activity_new_task is used to control the identity. If the identity causes an activity to start a new task, then when the user presses the home key to leave the activity, the user can no longer return to the original activity when he presses the back key. Some applications (such as notification) always open the activity in a new task and never open it in their own task, so they will always contain flag_activity_new_ The intent of the task is passed to StartActivity (). So if there is an activity that can be invoked by something else with this control flag, be aware that the application has an independent method of returning to the original activity. The code is as follows:

<activity android:name= "showmessageactivity" 
       android:launchmode= "Singletask" ></activity>  

The decision to switch before and after the Android application
does not provide a callback or broadcast in Android that can only be handled by ourselves. This problem was previously dealt with by implementing a baseactivity and then allowing all other activity to inherit from it, and then doing the corresponding testing in the lifecycle function. The specific detection methods are as follows:
       counts in the OnStart and OnStop methods of the activity, counting the variables to count, adding the variable to 1 in OnStart, OnStop minus 1, assuming there are two activity in the application, A and B respectively.
       First, start a,a and start B: Start A,count=1,a B, the order of the life cycle is b.onstart-> The count of A.onstop,count is still 1.
       Two, start a first, and then press home to return to the desktop: Start a,count=1, press home key to return to the desktop, will perform the a.onstop,count of the count of 0.
       from both of the above, you can tell that the application was cut from the foreground to the background by counting count 0. Similarly, cutting from the background to the front desk is similar. Look at the code behind the concrete implementation.
       But if not all of the activity in the project inherits from the same baseactivity, this functionality is not possible. Fortunately, Android, after API 14, in the application class, provides a registration method that applies lifecycle callbacks to centrally manage the lifecycle of an application, This interface is called Registeractivitylifecyclecallbacks, which registers its own activitylifecyclecallback, and each activity's lifecycle will be recalled to the corresponding method here. In fact, the nature of this registration method is the same as our implementation of baseactivity, just moving lifecycle management to the implementation of the activity itself.
  Use this method as follows:

public class MyApplication extends application{public int count = 0; 
 
    @Override public void OnCreate () {super.oncreate (); Registeractivitylifecyclecallbacks (New Activitylifecyclecallbacks () {@Override public void Onactivitystop 
        PED (activity activity) {LOG.V ("Viclee", Activity + "onactivitystopped"); 
        count--; if (count = = 0) {log.v ("Viclee", ">>>>>>>>>>>>>>>>>>> 
        Cut to backstage lifecycle "); @Override public void onactivitystarted (activity activity) {LOG.V ("Viclee"), the activity 
        + "onactivitystarted"); if (count = = 0) {log.v ("Viclee", ">>>>>>>>>>>>>>>>>>> 
        Cut to the front lifecycle "); 
      } count++; @Override public void onactivitysaveinstancestate (activity activity, Bundle outstate) {LOG.V (" Viclee ", Activity +"Onactivitysaveinstancestate "); @Override public void onactivityresumed (activity activity) {LOG.V ("Viclee", Activity + "onacti 
      Vityresumed "); @Override public void onactivitypaused (activity activity) {LOG.V ("Viclee", Activity + "Onactiv 
      Itypaused "); @Override public void onactivitydestroyed (activity activity) {LOG.V ("Viclee", Activity + "Onac 
      Tivitydestroyed "); @Override public void onactivitycreated (activity activity, Bundle savedinstancestate) {LOG.V (" 
      Viclee ", Activity +" onactivitycreated "); 
  } 
    }); 

 } 
}

In addition, is there any other way to achieve this?
when applied to the background, the process running in the foreground from our app into desktop app, based on this, we can detect the application of the switch before and after the function. Executing the detection code in the OnStop lifecycle of the activity, if it is found that the process currently running at the foreground is not our own process, the application is cut to the background.
Think about why you want to detect in OnStop, not onpause? This is because when A starts B, the lifecycle is executed in the following order:a.onpause->b.oncreate->b.onstart->b.onresume-> A.onstop, that is to say, in the OnPause method of a, B's lifecycle has not been implemented, the process has not entered the foreground, of course, is not detected. We moved the code to the OnPause lifecycle and found that it did not work. The
Implementation code is as follows:

Logic Private Boolean Iscurrentrunningforeground = True for controlling the switch before and after the application; 
   @Override protected void OnStart () {Super.onstart (); if (!iscurrentrunningforeground) {log.d (TAG, ">>>>>>>>>>>>>>>> 
   >>> cut to the foreground activity process "); 
   }} @Override protected void OnStop () {super.onstop (); 
   Iscurrentrunningforeground = Isrunningforeground (); if (!iscurrentrunningforeground) {log.d (TAG, ">>>>>>>>>>>>>>>> 
   >>> cut to background activity process "); } public boolean Isrunningforeground () {Activitymanager Activitymanager = (activitymanager) this.getsystemser 
   Vice (Context.activity_service); 
   list<activitymanager.runningappprocessinfo> Appprocessinfos = activitymanager.getrunningappprocesses (); Enumerates the processes for (Activitymanager.runningappprocessinfo Appprocessinfo:appprocessinfos) {if (appprocessinfo.import ance = = activitymanager.ruNningappprocessinfo.importance_foreground) {if (appProcessInfo.processName.equals) (This.getapplicationinfo (). Proc 
         Essname)) {LOG.D (TAG, "entryactivity isrunningforeground"); 
       return true; 
   }} log.d (TAG, "entryactivity isrunningbackground"); 
 return false; 
 }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.