Implication of android:process when defining services or receivers
will this have an impact on the behaviour of the receiver and SyncService?
Not directly.
Can this impact the applications' behaviour when running
Thread safety becomes a bit more of an issue with everything in one process. OTOH, that can be a lot easier than coordinating work in 2+ processes such that one process does not stomp on the work of the other process.
I am aware than a service will be run on the main thread
The lifecycle methods of a service (e.g., onStartCommand()
) will run on the main application thread; your business logic should run on background threads. You have to do that regardless of whether everything is in one process or split between processes.
will something stall or only delay when code is scheduled to run on the main thread?
If your service runs code on the main application thread, it will block everything else on that thread while that code runs. That is why services always use background threads.
Depending on how you are synchronizing access to shared objects, service code running on a background thread could lock access to those shared objects and therefore stall UI code that tries accessing those objects. That's why we try to organize our code to avoid blocking calls from the UI on such objects, such as by using reactive options (LiveData
, RxJava, etc.).
Every Activity in Android is a Process,or One Application is one process
All activities inside an application run in one process?
It depends on value of android:process
attribute in application manifest.
if attribute android:process
is not defined for Application/Activity tags in the manifest, by default all the activities will run in single process (process name will be name of the package defined in manifest)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.so.test" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Activity1">
</activity>
<activity android:name=".Activity2">
</activity>
<activity android:name=".Activity3">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
In the above manifest all activities run in process com.so.test
,ps command output in adb shell:
# ps
app_39 668 33 84492 20672 ffffffff afd0c51c S com.so.test
If android:process
is specified for Activity new process will be created with the same userid and the activity runs in that process.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.so.test" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:process="com.so.p1">
<activity android:name=".Activity1">
</activity>
<activity android:name=".Activity2" android:process="com.so.p2">
</activity>
<activity android:name=".Activity3" android:process="com.so.p3">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
If the manifest is defined like above
Activity1 runs in com.so.p1 process
Activity2 runs in com.so.p2 process
Activity3 runs in com.so.p3 process
ps output in adb shell
# ps
app_39 650 33 83192 20900 ffffffff afd0c51c S com.so.p1
app_39 659 33 83188 20864 ffffffff afd0c51c S com.so.p2
app_39 668 33 84492 20672 ffffffff afd0c51c S com.so.p3
If an Activity needs to be run in another process not defined in this manifest, both APKs should be signed with the same certificate.
Start a service in a separate process android
Check out the process
attribute for service
in AndroidManifest.xml
. You need to change your android:process
value to start with a :
.
http://developer.android.com/guide/topics/manifest/service-element.html
The relevant section:
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
The other answer provided doesn't really answer the question of how to start a service in a separate process.
Defining a Process of a Service
The android:process
field defines the name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. However, a component can override the default with its own process attribute, allowing you to spread your application across multiple processes.
If the name assigned to this attribute begins with a colon (':'), the service will run in its own separate process.
<service
android:name="com.example.appName"
android:process=":externalProcess" />
If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
android:process and process name
And what happens if I mix the two rules?
That's not possible. A colon is not a capital letter.
I need to have two components from two packages run in the same process to save resources (and to avoid having two "running apps" listed in the apps manager).
That's really not a good idea. Put them in the same package, or have them run independently.
Not only would you have to mess around with android:process
, but you also have to mess around with android:sharedUserId
. Neither of these are meant to be used by ordinary SDK developers, particularly android:sharedUserId
. In fact, if you have already distributed your application, you can't use android:sharedUserId
unless you're willing to break all your existing users' apps, since you will no longer be able to access your original data, since it'll be owned by some other user account.
Furthermore, unless you have evidence to the contrary, I would not assume that this will somehow "avoid having two 'running apps' listed in the apps manager".
Now, I am all for efficiency, and so creating extra processes for grins (e.g., misguided advice to make "remote services" run in custom processes) is a bad idea. And if you work for a device manufacturer or a firm with 20+ Android developers or something, and you want to mess around with this, you're going to need to find places where it is used in the AOSP and reverse-engineer the information you seek, since this stuff is seriously under-documented. And even there, I am not seeing it used between multiple packages, except for android.process.acore
and com.android.phone
, which are seriously low-level processes and are not going to be typical of non-firmware apps.
Hence, I really recommend that you leave these things alone.
processes & singleton in Android
- Does it mean there will be two JVM instances , one used by MyService while the other one used by other code?
yes (in a certain way, but not exactly, it's a dalvik VM, or in Lollipop ART), but yeah, you have two separate things running the service and rest of code.
- If the answer of above question is YES, then does it also mean if I have a singleton class used by both Activity & MyService, then there
will be two instances created for the singleton?
yes
- How to ensure only one instance be created & shared by two processes then? Better provide a sample :)
you can't! You just told the system to have separate processes. So it cannot have "the same" singleton.
An approach to that is have your service implement a binder or AIDL (in case you to direct calls methods) or implement a ContentProvider, which is the same across processes that you can read values out of it.
Or you can just make it all simpler and NOT use the process. 99.9% of use cases android:process
is not advised. So re-evaluate your software. Do you really need it?
edit:
unfortunately, my project need to use separate service process as it
has long running background tasks
If your project need a long running background task, you need a Service
for sure. But it doesn't mean it needs to be in a separate process. All the activities from your project can go to background and be garbage collected and your service still runs fine. It will keep running on the same process as the Activities were running but the Service and singletons will still be alive. Just remember to return START_STICKY
from it.
If you still think you need to use it in a separate process (I don't think you need). Then you need to implement a bound service (or maybe AIDL, I'm not sure bound service will work across process), connect the activity to it and give the reference of the object using a normal method like public void takeThisObJect(Object reference);
links to bound and AIDL service guides:
http://developer.android.com/guide/components/bound-services.html
http://developer.android.com/guide/components/aidl.html
how to get memory usage and cpu usage by application?
Context context = this.getApplicationContext();
ActivityManager mgr = (ActivityManager)context.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses();
Log.e("DEBUG", "Running processes:");
for(Iterator i = processes.iterator(); i.hasNext(); )
{
RunningAppProcessInfo p = (RunningAppProcessInfo)i.next();
Log.e("DEBUG", " process name: "+p.processName);
Log.e("DEBUG", " pid: "+p.pid);
int[] pids = new int[1];
pids[0] = p.pid;
android.os.Debug.MemoryInfo[] MI = mgr.getProcessMemoryInfo(pids);
Log.e("memory"," dalvik private: " + MI[0].dalvikPrivateDirty);
Log.e("memory"," dalvik shared: " + MI[0].dalvikSharedDirty);
Log.e("memory"," dalvik pss: " + MI[0].dalvikPss);
Log.e("memory"," native private: " + MI[0].nativePrivateDirty);
Log.e("memory"," native shared: " + MI[0].nativeSharedDirty);
Log.e("memory"," native pss: " + MI[0].nativePss);
Log.e("memory"," other private: " + MI[0].otherPrivateDirty);
Log.e("memory"," other shared: " + MI[0].otherSharedDirty);
Log.e("memory"," other pss: " + MI[0].otherPss);
Log.e("memory"," total private dirty memory (KB): " + MI[0].getTotalPrivateDirty());
Log.e("memory"," total shared (KB): " + MI[0].getTotalSharedDirty());
Log.e("memory"," total pss: " + MI[0].getTotalPss());
}
In modern OS, app use shared libraries. Hence, some memory is used
by multiple apps, complicating determining an apps memory usage.dalvikPrivateDirty is the memory that would be freed by the java
virtual machine if the process is killed- nativePrivateDirty is the same for native code is the same for some
other code (not sure what else there is) otherPrivateDirty dalvikSharedDirty is the shared memory used by the
java virtual machine But this would not be freedif this app is killed dalvikPss – an estimate of how much memory is
used by the app. This includes all the private memory, and a
fraction of the shared memory Check that pss >= private The reason
that only a fraction of shared memory is used is so that
reasonability of the shared memory usage across all responsible apps
This value is used to estimate the memory load of the app.
The totals are the sum over the dalvik, native, and other.
Related Topics
Creating Different Layout for Android Phone and Tablet
How to Switch Automatically Between Viewpager Pages
Set Language to French in Android Datepickerdialog
How to Stop/Cancel Android Countdowntimer
Android Change Text Color of Items in Spinner
Writing Text File to Sd Card Fails
Firebase Sort by Points Depending on Date
How to Use Broadcast Receiver in Different Applications in Android
Is Deprecated Word the Only Difference Between Fill_Parent and Match_Parent
Room - Livedata Observer Does Not Trigger When Database Is Updated
Java.Lang.Stackoverflow Error. Suspected Too Many Views
Firebase Token Authentication Error
The Import Android.Support.V7.App Cannot Be Resolved
Android Download PDF from Url Then Open It with a PDF Reader