最近遇到一個bug,當應用加了多進程後,好比總共進程數爲N,會出如今`startService()`時`onStartCommand()`方法會被重複調用`(N-1)`次的奇怪現象。android
***
## 禍起
>最近遇到兩個模塊互不相干卻受到影響的奇怪問題,一個push模塊和一個DaemonProcess模塊在一塊兒後,會出現以下現像的問題
***
當DaemonProcess爲應用加了多進程後,好比總共進程數爲N,會出現push模塊在`startService()`時`onStartCommand()`方法會被重複調用`(N-1)`次的奇怪現象。
***app
## 尋蹤ide
* 由於咱們用的是Jpush的緣由,一開始覺得是Jpush,但最後發現是由於引用多進程的緣由
* 再尋找下去發現 調用一次`startService()`時`onStartCommand()`運行屢次
* 而這二者有何關係呢測試
## 舉證this
> Demo測試:
> 首先在Application中申明四個service,其中`ServiceA`和`ServiceC`都各自另開一個進程,`ServiceB`和`ServiceD`都在主進程中,AndroidManifest.xml以下:xml
```進程
<service android:name=".ServiceA"
android:process="com.hujiang.test.servicea"
android:exported="true"/>
<service android:name=".ServiceB"
android:exported="false"/>
<service android:name=".ServiceC"
android:process="com.hujiang.test.servicec"
android:exported="true"/>get
<service android:name=".ServiceD"
android:exported="false"/>
```虛擬機
此時在Application中啓動四個Service
```it
startService(new Intent(this, ServiceA.class));
startService(new Intent(this, ServiceB.class));
startService(new Intent(this, ServiceC.class));
startService(new Intent(this, ServiceD.class));
```
同時各Service打下以下log:
```
public static final String TAG = ServiceB.class.getSimpleName();
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate" + "pid:" + android.os.Process.myPid());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG,"onStartCommand" + "pid:" + android.os.Process.myPid());
return super.onStartCommand(intent, flags, startId);
}
```
在log中會發現
`onCreate()`方法各執行一遍,這個是正常的,但`onStartCommand()`方法目前執行了三遍,由於共3個進程。
## 真相
1. N個進程,N個獨立的虛擬機,Application被N次初使化
2. 處理時應該在Application中分進程初始化數據
<!--more-->
## 劍譜
以下解決方案
mProcessName = getCurrentProcessName(this);
Log.i(TAG, "onCreate" + "getProcessName:" + mProcessName);
Log.i(TAG, "init_all_process");
if(TextUtils.equals(mProcessName, getPackageName())){
Log.i(TAG, "init_main_process");
} else if(TextUtils.equals(getProcessName(this, android.os.Process.myPid()), "com.hujiang.test.servicea")){
Log.i(TAG, "init_a_process");
}else if(TextUtils.equals(getProcessName(this, android.os.Process.myPid()), "com.hujiang.test.servicec")){
Log.i(TAG, "init_c_process");
}
獲取當前進程名稱:
private String getCurrentProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
分別在本身的進程中初始化