31-Jul-10 (Created: 31-Jul-10) | More in 'Android Core'

Android Architectural Predicates

On Process and Linux User Id

  1. An application represented by an apk file (usually) runs in its own proces
  2. Each such application or package runs under its own linux user id to create/access resources underneath
  3. Such a linux user id is usually auto generated
  4. You can assign an explicitly specified shared id to a package to run under.
  5. Each package or application in Android must be signed
  6. A shared id is unique across the system and not just with in your set of packages.
  7. The format of this id typically follows the java package structure to keep it unique.
  8. Two or more packages can specify the same shared user id as long as they are signed by the same certificate
  9. Once an application is in the market you can not turn on/off the shared id
  10. Once an application is in the market you can not reassign the shared id

Components and Threads

  1. An android application has 4 types of components a) Activity b) Content Provider c) Service d) Broadcast Receiver
  2. A single thread called main thread is used to run all the components
  3. The main thread is always responsible for the execution of the following a) Activty b) Local service that is accessed in-process c) Broadcast Receiever (whether local or remote)
  4. Thread pools are used to run the following cases a) Content providers accessed from outside b) Services that are bound from outside
  5. The thing about broadcast receivers is that even though they are frequently used to entertain outside clients they still run under the main thread.

Packages and Signatures

  1. You cannot have two distinct signatures for the same package. In otherwords two developers cannot install a package that carries the same package name.
  2. However same signature can be used to sign any number of packages
  3. One-to-many: In other words a "One" signature supports "Many" packages
  4. One-to-One: "One" package has one and only "One" signature
  5. Signatures are protected by developer using a password
  6. Keytool and Jarsigner are used to provision jar signing

Sharing Data

  1. One will use Context.createPackageContext() to get access to the package needed
  2. You can share more if both packages are signed with the same signature and they have the same shared id
  3. You can share another packages resources even if that package doesn't belong to you as long as that packages declares those resources to be sharable

Broadcast Receiver

  1. A broadcast receiver has a 10 sec limit before an ANR is prompted
  2. UI events have a 5 sec tolerance before an ANR is rushed
  3. A broadcast receiver can be local or remote
  4. A broadcast receiver is indicated by the tag
  5. To do long work in a broadcast reciver you must follow the following pattern a) tell the device to dont turn off by getting a wake lock b) start a service to keep the process alive c) start a thread d) when the thread finishes tell the service to stop, release the lock, and release the process e) Meanwhile return from the broadcast receiver as soon as the service is setup
  6. A sendBroadcast() call is used to start a broadcast receiver
  7. a sendBroadcast() although intent based, these intents never touch an activity or service
  8. A broadcast receiver has one method "onreceive"
  9. A broadcast reciever process is ready to go away as soon as teh "onreceive" finishes unless you have taken steps to convert the broadcastreceiver into a service
  10. You can have a broad cast receiver that doesnt have any intent filter. this is called a local only broadcast receiver
  11. you invoke local broad cast receivers with explicit class names
  12. An ANR shows up in two cases a) No UI response for 5 secs b) BroadcastReceiver hasn't returned in 10 secs

Activity Lifecycle Predicates

  1. When device changes configuration the activity in focus is restarted.
  2. When device changes configuration all started applications (processes) get notified of configuration change through an application call back
  3. When device chagnes configuration the activities that are not in focus but belong to the same application (or process) of the activity that is in focus ARE NOT restarted. However when you navigate to them at a later point through a back button they will also get started at that point
  4. If an activity is being shutdown due to config change, that activied is notified via "onRetainNonConfigurationInstance()"
  5. If an activity is being shutdown due to config change, that activied is notified also of "onSaveInstance" in anticipation of a "onRestoreInstance().
  6. onSaveInstance is called lot more often than onRestoreInstance
  7. When you navigate to a previously displayed activity the onRestoreInstance is not called because the activity is not destroed yet. Examples are going from a HOME button to a previously started App. Or going BACK from an activity with in your app to the other activity that started it.
  8. Even the onSaveInstance is not called at all if an activity is clearly being shutdown with no expectation from the user that it will keep its state. Example is going to a previous activity with in your app from the current activity.
  9. There is no explicit call that tells an activity that is beign started due to a config change that there is a config change. To know this you have to call "getLastConfigurationInstance()" which will return what is returned by "onRetainNonConfigurationInstance()"
  10. The common save/restore methods can be employed to deal with configuration change as well. These two methods are guranteed to be called in case of a configuration change.
  11. When you run low on memory it is possible that one of your own co-activities that are not in focus could be shut down and this reclamation is not limited to processes.
  12. onRestore is not called when you are visiting an activity whose visual state is not destroyed (Typically revisiting, with the exception where the activity is reclaimed)
  13. onSaveInstance is not called when you don't expect the activity to be revived with out explicit user intervention (Typicallly navigating back)
  14. An activity's state is not automatically maintained on configuration change. More accurately the activity's state is destroyed on configuration change.
  15. An activity's state is not destroyed when you navigate away from that activity with an expectation to return (For example hitting a BACK button doesnt count as expecting to return)

Activity Transitional Logic


H ---> A --(t1)--> B

H <-(t3)-- A <-(t2)-- B

H --(t4)--> A

A  --(c5)--> A

In the Diagram above upper case letters are Activites and lowercase letters are transitions. H - Home Activty, A - Activity A, B - Activity B. The "c5" is a transition change from the same activity to the same activity due to a configuration change.

On Transition "t1": When you go from A to B


A
  onSaveInstance
  onPause
  onStop

B
  onCreate
  onStart
  onResume
  
A
  onStop

Notice that on the activity you are navigating away from, "A" in this case, the onSaveInstance is called. However the view state is still intact in A as the "onDestroy" is not called. This means the "A" will retain its state even if you were to use transition "t2" and return to " A". So why would this then call "onsaveinstance"? Because, while "B" is being displayed it is possible that memory is low so "A" will be reclaimed in which case the "ondestroy" would be called. However when you go back to "A" from "B", android will restory "A" and calls the "onRestoreState". So if these two methods are not hooked up, it is possible that "A" will not retain state under low memory circumstances. Does it mean that onSaveInstance is called everytime an activity is destroyed? The answer is "no" as you will in the next transition.

On transition "t2": when you go from B to A


B
 onPause

A
 onRestart
 onStart
 onResume
 
B
 onStop
 onDestroy

Notice the behavior of "A" is expected. Because its view state is undisturbed its "onRestoreInstance()" is not called. However on activity "B" no effort is made to call the "onsaveinstance" nor does the system delay to call the "ondestroy". By explicitly choosing to visit the previous activity by using "BACK" the activity is literally removed from the stack of activities. If you were to invoke "B" again from "A" through an intent you will start it fresh.

On transition "t3": When you hit the home button on an activity


A
  onSaveInstance
  onPause
  onStop

Notice how even going to the home button the "onsaveinstance()" is called even though the "ondestroy" is not called yet. This is because while we are on the home and other apps perhaps, this activity could be reclaimed. It is also equally important to know that navigating from an activity to "HOME" and revisting it later would retain its state because the "ondestroy" is not called on that. So in other words from any activity you can navigate away either for a HOME or for another activity with in your app. The behavior is the same in both cases.

On transition "t4": When you revisit an activity


A 
    onRestart
    onStart
    onResume

Clearly the state of "A" is kept intact. If this activity had been reclaimed then you would have seen track like the following


A 
    onCreate
    onRestoreInstance
    onStart
    onResume

On Transition "c5": When an activity is restarted due to configuration change


Application
  configuration changed
  
A
  onSaveInstance
  onPause
  onStop
  onRetainNonConfigurationInstance
  onDestroy
  
A
  onCreate
  onStart
  onRestoreInstance
  onResume

What I don't know yet

  1. what is the structure and life time of auto generated linux user ids. Do they stick around? Does that have any adverse effect on the underlying linux process having to carry these additional userids?
  2. what is the motivation behind an explicitly class based in-process broadcast receiver? Can I just not use a function call?
  3. Why isnt there a version of broadcast receiver that is essentially service which we end up standing up using the same boiler plate code every time?

What resources have I used to gather this

I may have misread these resources below, but I didn't make up the above predicates.

1. http://developer.android.com/guide/topics/fundamentals.html#procthread

A link to understand the processes/threads/components. This is where google states thread pools for certain components.

2. http://developer.android.com/guide/topics/manifest/receiver-element.html

This is the link for the receiver element where they talk about local and remote receivers.

3. http://developer.android.com/guide/practices/design/responsiveness.html

This links talks about how broadcast receivers do indeed run on the main thread and that the 10 sec limitation is put on their responsiveness

4. http://stackoverflow.com/ ...android-how-to-share-code-between-projects

Read the restrictions on shared usedid from Dianne. Also the use of createPackageContext.

5. http://www.satyakomatineni.com/.....

You will see here a) how to sign apk files b) further links to how to share data between them c) share user id d) install/uninstall

6. http://developer.android.com/guide/publishing/app-signing.html

This link is a must read for signing apk files

7. http://java.sun.com/j2se/1.3/docs/tooldocs/win32/keytool.html

Excellent documentation on key tool, jar signer, and the signing process itself

8. http://www.satyakomatineni.com/....

My notes on understanding what it means to sign a jar file. A conceptual model