点击上方的终端研发部,右上角选择“设为星标

每日早9点半,技术文章准时送上

公众号后台回复“学习”,获取作者独家秘制精品资料

往期文章

一波Flutter酷炫特效来袭

今日头条屏幕适配方案落地研究

记五月的一个Android面试经

2018面试题之Bind机制完全总结

混合开发框架的对比,Flutter更胜一筹?

作者:minminaya链接:https://www.jianshu.com/p/b5371df6d7cb

一、常见保活方案

1、监听广播:监听全局的静态广播,比如时间更新的广播、开机广播、解锁屏、网络状态、解锁加锁亮屏暗屏(3.1版本),高版本需要应用开机后运行一次才能监听这些系统广播,目前此方案失效。可以更换思路,做APP启动后的保活(监听广播启动保活的前台服务)

2、定时器、JobScheduler:假如应用被系统杀死,那么定时器则失效,此方案失效。JobService在5.0,5.1,6.0作用很大,7.0时候有一定影响(可以在电源管理中给APP授权)

3、双进程(NDK方式Fork子进程)、双Service守护:高版本已失效,5.0起系统回收策略改成进程组。双Service方案也改成了应用被杀,任何后台Service无法正常状态运行

4、提高Service优先级:只能一定程度上缓解Service被立马回收

二、保活

  • 1、AIDL方式单进程、双进程方式保活Service

  • 2、降低oom_adj的值:常驻通知栏(可通过启动另外一个服务关闭Notification,不对oom_adj值有影响)、使用”1像素“的Activity覆盖在getWindow()的view上、循环播放无声音频(黑科技,7.0下杀不掉)

  • 3、监听锁屏广播:使Activity始终保持前台

  • 4、使用自定义锁屏界面:覆盖了系统锁屏界面。

  • 5、通过android:process属性来为Service创建一个进程

  • 6、跳转到系统白名单界面让用户自己添加app进入白名单

三、复活

  • 1、JobScheduler:原理类似定时器,5.0,5.1,6.0作用很大,7.0时候有一定影响(可以在电源管理中给APP授权)

  • 2、推送互相唤醒复活:极光、友盟、以及各大厂商的推送

  • 3、同派系APP广播互相唤醒:比如今日头条系、阿里系

方案实现效果统计

1、双进程守护方案(基于onStartCommand() return START_STICKY)

  • 1、原生5.0、5.1:原生任务栏滑动清理app,Service会被杀掉,然后被拉起,接着一直存活

  • 2、金立F100(5.1):一键清理直接杀掉整个app,包括双守护进程。不手动清理情况下,经测试能锁屏存活至少40分钟

  • 3、华为畅享5x(6.0):一键清理直接杀掉整个app,包括双守护进程。不手动清理下,锁屏只存活10s。结论:双进程守护方案失效。

  • 4、美图m8s(7.1.1):一键清理直接杀掉整个app,包括双守护进程。不清理情况下,锁屏会有被杀过程(9分钟左右被杀),之后重新复活,之后不断被干掉然后又重新复活。结论:双守护进程可在后台不断拉起Service。

  • 5、原生7.0:任务栏清除APP后,Service存活。使用此方案后Service照样存活。

  • 6、LG V30+(7.1.2):不加双进程守护的时候,一键清理无法杀掉服务。加了此方案之后也不能杀掉服务,锁屏存活(测试观察大于50分钟)

  • 7、小米8(8.1):一键清理直接干掉app并且包括双守护进程。不清理情况下,不加守护进程方案与加守护进程方案Service会一直存活,12分钟左右closed。结论:此方案没有起作用

结论:除了华为此方案无效以及未更改底层的厂商不起作用外(START_STICKY字段就可以保持Service不被杀)。此方案可以与其他方案混合使用

2、监听锁屏广播打开1像素Activity(基于onStartCommand() return START_STICKY)
  • 1、原生5.0、5.1:锁屏后3s服务被干掉然后重启(START_STICKY字段起作用)

  • 2、华为畅享5x(6.0):锁屏只存活4s。结论:方案失效。

  • 3、美图m8s(7.1.1):同原生5.0

  • 4、原生7.0:同美图m8s。

  • 5、LG V30+(7.1.2):锁屏后情况跟不加情况一致,服务一致保持运行,结论:此方案不起作用

  • 6、小米8(8.1):关屏过2s之后app全部被干掉。结论:此方案没有起作用

结论:此方案无效果

3、故意在后台播放无声的音乐(基于onStartCommand() return START_STICKY)

  • 1、原生5.0、5.1:锁屏后3s服务被干掉然后重启(START_STICKY字段起作用)

  • 2、华为畅享5x(6.0):一键清理后服务依然存活,需要单独清理才可杀掉服务,锁屏8分钟后依然存活。结论:此方案适用

  • 3、美图m8s(7.1.1):同5.0

  • 4、原生7.0:任务管理器中关闭APP后服务被干掉,大概过3s会重新复活(同仅START_STICKY字段模式)。结论:看不出此方案有没有其作用

  • 5、LG V30+(7.1.2):使用此方案前后效果一致。结论:此方案不起作用

  • 6、小米8(8.1):一键清理可以杀掉服务。锁屏后保活超过20分钟

结论:成功对华为手机保活。小米8下也成功突破20分钟

4、使用JobScheduler唤醒Service(基于onStartCommand() return START_STICKY)

  • 1、原生5.0、5.1:任务管理器中干掉APP,服务会在周期时间后重新启动。结论:此方案起作用

  • 2、华为畅享5x(6.0):一键清理直接杀掉APP,过12s左右会自动重启服务,JobScheduler起作用

  • 3、美图m8s(7.1.1):一键清理直接杀掉APP,无法自动重启

  • 4、原生7.0:同美图m8s(7.1.1)

  • 5、小米8(8.1):同美图m8s(7.1.1)

结论:只对5.0,5.1、6.0起作用

5、混合使用的效果,并且在通知栏弹出通知

  • 1、原生5.0、5.1:任务管理器中干掉APP,服务会在周期时间后重新启动。锁屏超过11分钟存活

  • 2、华为畅享5x(6.0):一键清理后服务依然存活,需要单独清理才可杀掉服务。结论:方案适用。

  • 3、美图m8s(7.1.1):一键清理APP会被杀掉。正常情况下锁屏后服务依然存活。

  • 4、原生7.0:任务管理器中关闭APP后服务被干掉,过2s会重新复活

  • 5、小米8(8.1):一键清理可以杀掉服务,锁屏下后台保活时间超过38分钟

  • 6、荣耀10(8.0):一键清理杀掉服务,锁屏下后台保活时间超过23分钟

结论:高版本情况下可以使用弹出通知栏、双进程、无声音乐提高后台服务的保活概率

实现具体过程

一、双进程实现方案

使用AIDL绑定方式新建2个Service优先级(防止服务同时被系统杀死)不一样的守护进程互相拉起对方,并在每一个守护进程的ServiceConnection的绑定回调里判断保活Service是否需要重新拉起和对守护线程进行重新绑定。

1、新建一个AIDL文件

KeepAliveConnection
interface KeepAliveConnection  {
}

2、新建一个服务类StepService,onBind()方法返回new KeepAliveConnection.Stub()对象,并在ServiceConnection的绑定回调中对守护进程服务类GuardService的启动和绑定。

/**
* 主进程 双进程通讯
*
* @author LiGuangMin
* @time Created by 2018/8/17 11:26
*/
public class StepService extends Service {private final static String TAG = StepService.class.getSimpleName();private ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Logger.d(TAG, "StepService:建立链接");boolean isServiceRunning = ServiceAliveUtils.isServiceAlice();if (!isServiceRunning) {Intent i = new Intent(StepService.this, DownloadService.class);startService(i);}}@Overridepublic void onServiceDisconnected(ComponentName componentName) {// 断开链接startService(new Intent(StepService.this, GuardService.class));// 重新绑定bindService(new Intent(StepService.this, GuardService.class), mServiceConnection, Context.BIND_IMPORTANT);}};@Nullable@Overridepublic IBinder onBind(Intent intent) {return new KeepAliveConnection.Stub() {};}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {startForeground(1, new Notification());// 绑定建立链接bindService(new Intent(this, GuardService.class), mServiceConnection, Context.BIND_IMPORTANT);return START_STICKY;}}

3、对守护进程GuardService进行和2一样的处理

/**
* 守护进程 双进程通讯
*
* @author LiGuangMin
* @time Created by 2018/8/17 11:27
*/
public class GuardService extends Service {private final static String TAG = GuardService.class.getSimpleName();private ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Logger.d(TAG, "GuardService:建立链接");boolean isServiceRunning = ServiceAliveUtils.isServiceAlice();if (!isServiceRunning) {Intent i = new Intent(GuardService.this, DownloadService.class);startService(i);}}@Overridepublic void onServiceDisconnected(ComponentName componentName) {// 断开链接startService(new Intent(GuardService.this, StepService.class));// 重新绑定bindService(new Intent(GuardService.this, StepService.class), mServiceConnection, Context.BIND_IMPORTANT);}};@Nullable@Overridepublic IBinder onBind(Intent intent) {return new KeepAliveConnection.Stub() {};}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {startForeground(1, new Notification());// 绑定建立链接bindService(new Intent(this, StepService.class), mServiceConnection, Context.BIND_IMPORTANT);return START_STICKY;}}

4、在Activity中在启动需要保活的DownloadService服务后然后启动保活的双进程

public class MainActivity extends AppCompatActivity {private TextView mShowTimeTv;private DownloadService.DownloadBinder mDownloadBinder;private ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mDownloadBinder = (DownloadService.DownloadBinder) service;mDownloadBinder.setOnTimeChangeListener(new DownloadService.OnTimeChangeListener() {@Overridepublic void showTime(final String time) {runOnUiThread(new Runnable() {@Overridepublic void run() {mShowTimeTv.setText(time);}});}});}@Overridepublic void onServiceDisconnected(ComponentName name) {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, DownloadService.class);startService(intent);bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);//双守护线程,优先级不一样startAllServices();}@Overridepublic void onContentChanged() {super.onContentChanged();mShowTimeTv = findViewById(R.id.tv_show_time);}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mServiceConnection);}/*** 开启所有守护Service*/private void startAllServices() {startService(new Intent(this, StepService.class));startService(new Intent(this, GuardService.class));}
}

二、监听到锁屏广播后使用“1”像素Activity提升优先级

1、该Activity的View只要设置为1像素然后设置在Window对象上即可。在Activity的onDestroy周期中进行保活服务的存活判断从而唤醒服务。”1像素”Activity如下

public class SinglePixelActivity extends AppCompatActivity {private static final String TAG = SinglePixelActivity.class.getSimpleName();@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);Window mWindow = getWindow();mWindow.setGravity(Gravity.LEFT | Gravity.TOP);WindowManager.LayoutParams attrParams = mWindow.getAttributes();attrParams.x = 0;attrParams.y = 0;attrParams.height = 1;attrParams.width = 1;mWindow.setAttributes(attrParams);ScreenManager.getInstance(this).setSingleActivity(this);}@Overrideprotected void onDestroy() {if (!SystemUtils.isAppAlive(this, Constant.PACKAGE_NAME)) {Intent intentAlive = new Intent(this, DownloadService.class);startService(intentAlive);}super.onDestroy();}
}

2、对广播进行监听,封装为一个ScreenReceiverUtil类,进行锁屏解锁的广播动态注册监听

public class ScreenReceiverUtil {private Context mContext;private SreenBroadcastReceiver mScreenReceiver;private SreenStateListener mStateReceiverListener;public ScreenReceiverUtil(Context mContext) {this.mContext = mContext;}public void setScreenReceiverListener(SreenStateListener mStateReceiverListener) {this.mStateReceiverListener = mStateReceiverListener;// 动态启动广播接收器this.mScreenReceiver = new SreenBroadcastReceiver();IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);filter.addAction(Intent.ACTION_USER_PRESENT);mContext.registerReceiver(mScreenReceiver, filter);}public void stopScreenReceiverListener() {mContext.unregisterReceiver(mScreenReceiver);}/*** 监听sreen状态对外回调接口*/public interface SreenStateListener {void onSreenOn();void onSreenOff();void onUserPresent();}public class SreenBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (mStateReceiverListener == null) {return;}if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏mStateReceiverListener.onSreenOn();} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏mStateReceiverListener.onSreenOff();} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁mStateReceiverListener.onUserPresent();}}}
}

3、对1像素Activity进行防止内存泄露的处理,新建一个ScreenManager类

public class ScreenManager {private static final String TAG = ScreenManager.class.getSimpleName();private static ScreenManager sInstance;private Context mContext;private WeakReference<Activity> mActivity;private ScreenManager(Context mContext) {this.mContext = mContext;}public static ScreenManager getInstance(Context context) {if (sInstance == null) {sInstance = new ScreenManager(context);}return sInstance;}/** 获得SinglePixelActivity的引用* @param activity*/public void setSingleActivity(Activity activity) {mActivity = new WeakReference<>(activity);}/*** 启动SinglePixelActivity*/public void startActivity() {Intent intent = new Intent(mContext, SinglePixelActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mContext.startActivity(intent);}/*** 结束SinglePixelActivity*/public void finishActivity() {if (mActivity != null) {Activity activity = mActivity.get();if (activity != null) {activity.finish();}}}
}

4、对1像素的Style进行特殊处理,在style文件中新建一个SingleActivityStyle

<style name="SingleActivityStyle" parent="android:Theme.Holo.Light.NoActionBar"><item name="android:windowBackground">@android:color/transparent</item><item name="android:windowFrame">@null</item><item name="android:windowNoTitle">true</item><item name="android:windowIsFloating">true</item><item name="android:windowContentOverlay">@null</item><item name="android:backgroundDimEnabled">false</item><item name="android:windowAnimationStyle">@null</item><item name="android:windowDisablePreview">true</item><item name="android:windowNoDisplay">false</item>

5、让SinglePixelActivity使用singleInstance启动模式,在manifest文件中

<activityandroid:name=".activity.SinglePixelActivity"android:configChanges="keyboardHidden|orientation|screenSize|navigation|keyboard"android:excludeFromRecents="true"android:finishOnTaskLaunch="false"android:launchMode="singleInstance"android:theme="@style/SingleActivityStyle" />

6、在保活服务类DownloadService中对监听的广播进行注册和对SinglePixelActivity进行控制

public class DownloadService extends Service {public static final int NOTICE_ID = 100;private static final String TAG = DownloadService.class.getSimpleName();private DownloadBinder mDownloadBinder;private NotificationCompat.Builder mBuilderProgress;private NotificationManager mNotificationManager;private ScreenReceiverUtil mScreenListener;private ScreenManager mScreenManager;private Timer mRunTimer;private int mTimeSec;private int mTimeMin;private int mTimeHour;private ScreenReceiverUtil.SreenStateListener mScreenListenerer = new ScreenReceiverUtil.SreenStateListener() {@Overridepublic void onSreenOn() {mScreenManager.finishActivity();Logger.d(TAG, "关闭了1像素Activity");}@Overridepublic void onSreenOff() {mScreenManager.startActivity();Logger.d(TAG, "打开了1像素Activity");}@Overridepublic void onUserPresent() {}};private OnTimeChangeListener mOnTimeChangeListener;@Overridepublic void onCreate() {super.onCreate();//        注册锁屏广播监听器mScreenListener = new ScreenReceiverUtil(this);mScreenManager = ScreenManager.getInstance(this);mScreenListener.setScreenReceiverListener(mScreenListenerer);mDownloadBinder = new DownloadBinder();mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Logger.d(TAG, "onStartCommand");startRunTimer();return START_STICKY;}@Nullable@Overridepublic IBinder onBind(Intent intent) {return mDownloadBinder;}@Overridepublic boolean onUnbind(Intent intent) {Logger.d(TAG, "onUnbind");return super.onUnbind(intent);}@Overridepublic void onDestroy() {super.onDestroy();NotificationManager mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);if (mManager == null) {return;}mManager.cancel(NOTICE_ID);stopRunTimer();
//        mScreenListener.stopScreenReceiverListener();}private void startRunTimer() {TimerTask mTask = new TimerTask() {@Overridepublic void run() {mTimeSec++;if (mTimeSec == 60) {mTimeSec = 0;mTimeMin++;}if (mTimeMin == 60) {mTimeMin = 0;mTimeHour++;}if (mTimeHour == 24) {mTimeSec = 0;mTimeMin = 0;mTimeHour = 0;}String time = "时间为:" + mTimeHour + " : " + mTimeMin + " : " + mTimeSec;if (mOnTimeChangeListener != null) {mOnTimeChangeListener.showTime(time);}Logger.d(TAG, time);}};mRunTimer = new Timer();// 每隔1s更新一下时间mRunTimer.schedule(mTask, 1000, 1000);}private void stopRunTimer() {if (mRunTimer != null) {mRunTimer.cancel();mRunTimer = null;}mTimeSec = 0;mTimeMin = 0;mTimeHour = 0;Logger.d(TAG, "时间为:" + mTimeHour + " : " + mTimeMin + " : " + mTimeSec);}public interface OnTimeChangeListener {void showTime(String time);}public class DownloadBinder extends Binder {public void setOnTimeChangeListener(OnTimeChangeListener onTimeChangeListener) {mOnTimeChangeListener = onTimeChangeListener;}}
}

3、在后台播放音乐

1、准备一段无声的音频,新建一个播放音乐的Service类,将播放模式改为无限循环播放。在其onDestroy方法中对自己重新启动。

public class PlayerMusicService extends Service {private final static String TAG = PlayerMusicService.class.getSimpleName();private MediaPlayer mMediaPlayer;@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Logger.d(TAG, TAG + "---->onCreate,启动服务");mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.silent);mMediaPlayer.setLooping(true);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {startPlayMusic();}}).start();return START_STICKY;}private void startPlayMusic() {if (mMediaPlayer != null) {Logger.d(TAG, "启动后台播放音乐");mMediaPlayer.start();}}private void stopPlayMusic() {if (mMediaPlayer != null) {Logger.d(TAG, "关闭后台播放音乐");mMediaPlayer.stop();}}@Overridepublic void onDestroy() {super.onDestroy();stopPlayMusic();Logger.d(TAG, TAG + "---->onCreate,停止服务");// 重启自己Intent intent = new Intent(getApplicationContext(), PlayerMusicService.class);startService(intent);}
}

2、在保活的DownloadServie服务类的onCreate方法中对PlayerMusicService进行启动

Intent intent = new Intent(this, PlayerMusicService.class);
startService(intent);

3、在Manifest文件中进行注册

<serviceandroid:name=".service.PlayerMusicService"android:enabled="true"android:exported="true"android:process=":music_service" />

4、使用JobScheduler唤醒Service

1、新建一个继承自JobService的ScheduleService类,在其onStartJob回调中对DownloadService进行存活的判断来重启。

public class ScheduleService extends JobService {private static final String TAG = ScheduleService.class.getSimpleName();@Overridepublic boolean onStartJob(JobParameters params) {boolean isServiceRunning = ServiceAliveUtils.isServiceAlice();if (!isServiceRunning) {Intent i = new Intent(this, DownloadService.class);startService(i);Logger.d(TAG, "ScheduleService启动了DownloadService");}jobFinished(params, false);return false;}@Overridepublic boolean onStopJob(JobParameters params) {return false;}
}

2、 在DownloadService服务类中进行JobScheduler的注册和使用

/*** 使用JobScheduler进行保活*/private void useJobServiceForKeepAlive() {JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);if (jobScheduler == null) {return;}jobScheduler.cancelAll();JobInfo.Builder builder =new JobInfo.Builder(1024, new ComponentName(getPackageName(), ScheduleService.class.getName()));//周期设置为了2sbuilder.setPeriodic(1000 * 2);builder.setPersisted(true);builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);int schedule = jobScheduler.schedule(builder.build());if (schedule <= 0) {Logger.w(TAG, "schedule error!");}}

3、在manifest文件中进行权限设置

<serviceandroid:name=".service.ScheduleService"android:enabled="true"android:exported="true"android:permission="android.permission.BIND_JOB_SERVICE" />

关于推送类拉活

根据华为官方文档集成HUAWEI Push

  • 1、华为畅玩5X(6.0):APP全部进程被杀死时可以被拉起。

  • 2、华为nove 3e(8.0):APP全部进程被杀死时无法被拉起,能收到推送。

  • 3、华为荣耀10(8.1):同2

结论:理论情况下,华为推送应该可以拉起华为机器才对,感觉是我没花钱的原因

补充:ServiceAliveUtils 类如下
public class ServiceAliveUtils {public static boolean isServiceAlice() {boolean isServiceRunning = false;ActivityManager manager =(ActivityManager) MyApplication.getMyApplication().getSystemService(Context.ACTIVITY_SERVICE);if (manager == null) {return true;}for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {if ("demo.lgm.com.keepalivedemo.service.DownloadService".equals(service.service.getClassName())) {isServiceRunning = true;}}return isServiceRunning;}
}

What外包,技术外包如何防坑?

Github几个非常值得学习的项目

Android 架构组件 - 让天下没有难做的 App

手机商对“鸿蒙”进行了密集测试:比安卓系统快?

相信自己,没有做不到的,只有想不到的

在这里获得的不仅仅是技术!

喜欢就给个“在看” 

Android的保活方案效果统计相关推荐

  1. 2018年Android的保活方案效果统计

    一.常见保活方案 1.监听广播:监听全局的静态广播,比如时间更新的广播.开机广播.解锁屏.网络状态.解锁加锁亮屏暗屏(3.1版本),高版本需要应用开机后运行一次才能监听这些系统广播,目前此方案失效.可 ...

  2. 全面盘点当前Android后台保活方案的真实运行效果(截止2019年前)

    全面盘点当前Android后台保活方案的真实运行效果(截止2019年前) 本文原作者"minminaya",作者网站:minminaya.cn,为了提升文章品质,即时通讯网对内容作 ...

  3. 2018年最新Android的保活方案及效果统计

    热文导读 | 点击标题阅读 金九银十跳槽季如何进阶找到合适满意的工作? 要么干,要么辞职,千万别混 重磅:Android 技能图谱学习路线 作者:minminaya https://www.jians ...

  4. Android 进程保活方案

    前言 Android 系统为了保持系统运行流畅,在内存吃紧的情况下,会将一些进程给杀掉,以释放一部分内存.然而,对于一些(如:QQ.微信等)比较重要的.我们希望能及时收到消息的App,需要保持进程持续 ...

  5. Android进程保活方案

    自己曾经也在这个问题上伤过脑经,前几日刚好有一个北京的哥们在QQ说在做IM类的项目,问我进程保活如何处理比较恰当,决定去总结一下,网上搜索一下进程常驻的方案好多好多,但是很多的方案都是不靠谱的或者不是 ...

  6. Android进程保活方案的几种方案

    自己曾经也在这个问题上伤过脑经,前几日刚好有一个北京的哥们在QQ说在做IM类的项目,问我进程保活如何处理比较恰当,决定去总结一下,网上搜索一下进程常驻的方案好多好多,但是很多的方案都是不靠谱的或者不是 ...

  7. 盘点im即时通讯开发中Android后台保活方案

    对于IM应用和消息推送服务的开发者来说,在Android机型上的后台保活是个相当头疼的问题. 老板一句:"为什么微信.QQ能收到消息,而你写的APP却不行?",直接让人崩溃,话说老 ...

  8. Android进程保活--我也想乖,傻C产品就要这样

    方案 推送,保活. Netty长链接很成熟. 双service保活.(7.0已失效,阿里大神) 标题 重点内容 探讨Android6.0及以上系统APP常驻内存(保活)实现-复活篇 探讨Android ...

  9. Android进程保活(常驻内存)

    Android将进程分为6个等级,它们按优先级顺序由高到低依次是:  1.前台进程( FOREGROUND_APP):  2.可视进程(VISIBLE_APP ):  3. 次要服务进程(SECOND ...

最新文章

  1. Java Web整合开发(10) -- 资源国际化
  2. 无法启动此程序因为计算机中丢失msvcr110,无法启动此程序因为计算机中丢失msvcr110,教您无法运行程序提示计算机中丢失...
  3. 请举例说明@Qualifier 注解?
  4. 被忽略的知识点——switch语句
  5. arcgis9.2的安装方法
  6. 基于stm32f429的手写识别_关注智能手机老年用户:百度输入法手写模型迎来重磅升级...
  7. linux中断处理汇编入口,Linux中断处理体系结构分析(一)
  8. [论文阅读][ICP变种] Generalized-ICP
  9. lucene-SpanQuery跨度查询基础
  10. 智能优化算法:鸟群算法-附代码
  11. SQL数据库异地备份(小白篇)两台服务器之间备份
  12. win10计算机系统慢,升级Win10后电脑变慢了?老电脑装Win7、Win10流畅性测试
  13. UIDataCollector的下载和使用
  14. requests模块练习1
  15. [HDU 5755] Gambler Bo (高斯消元)
  16. 卧底“刷量”卖家,有关微信公众号“刷量”的五个劲爆事实
  17. python能在业余时间赚钱吗?分享自己的接私活经验及学习经验
  18. 【Redis-09】面试题之Redis数据结构与对象-RedisObject(下篇)
  19. 2022哈工大软件构造lab1小结(知识点)
  20. 微信小程序cameraContext拍摄的视频或照片上传后端,不需要处理实时监听的ArrayBuffer格式的视频数据,只需要直接使用wx.uploadFile上传后端,简单好用(带前后端代码)

热门文章

  1. 循环队列的基本操作(实验)
  2. 任务42:EF Core Migration
  3. 查看wifi密码-(鸡贼小技巧)
  4. 关于海思3536编解码与FFmpeg的相关问题——推流相关
  5. CC(标准)版D碟收藏指南(前言)
  6. IT互联网领军者眼中的2013年
  7. React中受控组件和非受控组件 1
  8. R语言epiDisplay包的tab1函数计算数据框中指定变量的频率并可视化(一维频率表、频数的百分比、累积的百分比、使用条形图可视化频数分布)、自定义设置cum.percent参数是否显示累积百分比
  9. 读书笔记-让别人主动赞美你的能力而不是自夸
  10. element card实现边框有弧度