小结: application 在oncreate 的时候 开启线程,在线程里面进行sdk 初始化操作
问题 :IntentService 走了2到3次,开始考虑采用一个 boolean 类型判断,可还是走了2次,后来看application 会走两次,参考https://blog.csdn.net/try_zp_catch/article/details/72649638
完美解决
思路是 因为进程开启了两次application,对application 进程进程判断,如果是自己包名的进程则初始化,否则不处理。
intentservice 是系统提供的自带子线程的服务,自动完成后关闭,提供onHandleIntent 接口来处理 初始化的逻辑 ------用完就关闭
application
public void onCreate() {
String processName = SystemUtils.getProcessName(this, android.os.Process.myPid());
if(processName != null){
boolean defaultProcess = processName.equals("com.包名");
if(defaultProcess){
//当前应用的初始化
Log.e ("hyl","application create SystemUtils.getProcessName");
InitAppService.start (this);//初始化数据
}
}
}
public class InitAppService extends IntentService {
private static final String TAG = "InitAppService";
private static final String ACTION_INIT = "initApplication";
public static boolean ISDEBUG = BuildConfig.LOG_DEBUG;//调试时为true
private boolean isInit=false;
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public InitAppService(String name) {
super (name);
}
public InitAppService() {
super (ACTION_INIT);
}
public static void start(Context context) {
Intent intent = new Intent(context, InitAppService.class);
intent.setAction(ACTION_INIT);
context.startService(intent);
MyLog.wtf ("hyl","InitAppService +start");
}
// debug 发现onHandleIntent 方法会执行3次,采用一个字段 使得其只接受一次数据
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (intent == null) {
return;
}
final String action = intent.getAction();
if (!ACTION_INIT.equals(action)) {
return;
}
if(isInit==true){
return;
}
//初始化数据处理
/*添加 logger 管理*/
if (ISDEBUG) {
CrashHandler.getInstance().init(App.getContext ());
Logger.init();
} else {
CrashHandler.getInstance().init(App.getContext ());
Logger.init().logLevel(LogLevel.NONE);
}
isInit=true;
}
}
引用内容
在做"个推"时发现官方文档中有这么一个注释:
该方法必须在Activity或Service类内调用,一般情况下,可以在Activity的onCreate()方法中调用。由于应用每启动一个新的进程,就会调用一次Application的onCreate()方法,而个推SDK是一个独立的进程,因此如果在Application的onCreate()中调用intialize接口,会导致SDK初始化在一个应用中多次调用,所以不建议在Application继承类中调用个推SDK初始化接口。
解释一下,每个[Android](http://lib.csdn.net/base/android "Android知识库")应用都要运行在一个虚拟机上,”个推“采用Service和后台服务器通信进行通信,于是和原本的Activity就形成了多进程。一个前台的应用进程,一个service后台进程,每个进程对应一个application对象,所以当应用配置了多个进程的时候,application对象的onCreate方法就会执行多次,所以为了保证只初始化一次,就必须做出区分的处理的(“个推”中提到的在Activity或Service中初始,这种做法个人认为也是存在多次初始化的风险的);
进程名是通过Manifest.xml中的"android:process"属性设置的,因此可以在application的onCreate方法中通过pid获取processName,再做进一步的判断(跟android:process的值进行判断)使得相关初始化代码仅执行一次。
在application中添加如下代码:
public class SystemUtils {
public static String getProcessName(Context cxt, int pid) {
ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (ActivityManager.RunningAppProcessInfo procInfo : runningApps) {
if (procInfo.pid == pid) {
return procInfo.processName;
}
}
return null;
}
}
网友评论