Android系统会在内存不足的时候去将进程杀死,俗称Low Memory Killer,它是 基于linux内核的 OOM Killer(Out-Of-Memory killer)机制,内存不足时,优先杀oom_adj值高的进程(此值越高,代表该进程越不重要)。对于公司来说,当然都希望自己APP的进程尽量的不被杀死,于是乎,就有了一些列进程保活的方法出现。
进程的重要性,划分5级:
A. 拥有用户正在交互的 Activity(已调用 onResume())
B. 拥有某个 Service,后者绑定到用户正在交互的 Activity
C. 拥有正在“前台”运行的 Service(服务已调用 startForeground())
D. 拥有正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
E. 拥有正执行其 onReceive() 方法的 BroadcastReceiver
A. 拥有不在前台、但仍对用户可见的 Activity(已调用 onPause())。
B. 拥有绑定到可见(或前台)Activity 的 Service
A. 正在运行 startService() 方法启动的服务,且不属于上述两个更高类别进程的进程。
A. 对用户不可见的 Activity 的进程(已调用 Activity的onStop() 方法)
A. 不含任何活动应用组件的进程
将服务写为前台服务
https://blog.csdn.net/amynn/article/details/106984939
说明:在service的onStartCommand方法里返回 STATR_STICK
START_NOT_STICKY:表示当Service运行的进程被Android系统强制杀掉之后,不会重新创建该Service,如果想重新实例化该Service,就必须重新调用startService来启动。
START_STICKY:表示Service运行的进程被Android系统强制杀掉之后,Android系统会将该Service依然设置为started状态(即运行状态),但是不再保存onStartCommand方法传入的intent对象。
START_REDELIVER_INTENT:表示Service运行的进程被Android系统强制杀掉之后,Intent保留下来并再次传入到重新创建后的Service的onStartCommand方法中,这样我们就能读取到intent参数。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
//return super.onStartCommand(intent, flags, startId);
}
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
@Override
public void onDestroy() {
//服务销毁时再次启动
Intent intent = new Intent(this, KeeLiveService.class);
startService(intent);
super.onDestroy();
}
思路:在发生特定系统事件时,系统会发出响应的广播,通过在 AndroidManifest 中“静态”注册对应的广播监听器,即可在发生响应事件时拉活。
获得如:手机QQ、微信、支付宝、UC浏览器等,以及友盟、信鸽、个推等 SDK,找出它们外发的广播,在应用中进行监听,这样当这些应用发出广播时,就会将我们的应用拉活。
该方案主要适用于 Android5.0 以下版本手机
Android5.0 以后系统对 Native 进程等加强了管理,Native 拉活方式失效。系统在 Android5.0 以上版本提供了 JobScheduler 接口,系统会定时调用该进程以使应用进行一些逻辑操作。
思路:
1.监听手机锁屏按钮(Intent.ACTION_SCREEN_OFF)当手机锁屏时,启动Activity(此Activity不能被用户发现,所以可以将Activity设置为透明)
2.监听手机开屏按钮(Intent.ACTION_SCREEN_ON)当手机开屏时,结束此页面
<style name="OnePxActStyle">
<!-- 窗体背景颜色为透明 -->
<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>
<!-- 自定义TitleBar时去掉多余的阴影-->
<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>
</style>
相当于开启了计时器
public class Services2 extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
Log.d("amy","onStart");
startJobService();
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
Log.d("amy","onStopJob");
return false;
}
public void startJobService(){
JobScheduler jobScheduler = (JobScheduler) this.getSystemService(JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(100,
new ComponentName(getPackageName(),Services2.class.getName())).setPersisted(true);
jobScheduler.schedule(builder.build());
}
}
<service android:name=".Services2" />
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Services2().startGuardJob();
}
}
所谓 A/B 测试,简单来说,就是为同一个目标制定两个方案(比如两个页面),让一部分用户使用 A 方案,另一部分用户使用 B 方案,记录下用户的使用情况,看哪个方案更符合设计目标。