android进程保活-前台server+像素保活

借鉴部分

背景:从产品的角度来说,任何一个应用程序的PM都希望自己的应用程序在用户手机中的留存率高些些,之前我接触到的一个业务需求也是如此,要求提升应用程序在国内第三方厂商ROM中的存活率。

如前篇所述踩坑篇,保活策略只在android原生系统中起作用,在国内第三方厂商ROM中是没有效果的。为了提高app在第三方ROM中的存活率,调研了一些方法,最终选择某移动社交应用的1像素保活方案,因为这个方案人家没有开源,所以只能自己动手。


针对国内第三方厂商ROM在退屏后应用很快被杀的调查发现,原生系统在内存充足的情况下,用户执行熄屏的操作不会立即kill app,但是第三方ROM会,推测是修改了ROM在熄屏时执行了内存清理工作,不论此时手机内存是否充足都执行清理。对于没有加入到厂家ROM清理白名单中的app,不可避免的被杀。当然有的人会不同意,说像QQ,微信之类的就没有在熄屏后被杀,用户也没有手动将其加入系统白名单中。这种情况是QQ和微信已经加入到系统的白名单中了,当然不需要用户手动添加了。不过这已经经 是技术人员可以解决的了,需要双方的商务洽谈了。


我在使用国内第三方ROM MIUI时发现,如果保持当前应用在前台存活,执行熄屏,分别等待1分钟,5分钟,10分钟后,再次打开屏幕时,app会存活,即使被杀掉也会重新启动。基与此并结合1像素保活方案,我在应用程序启动时注册一个监听器监听屏幕亮屏熄屏,当用户启动我的应用程序时,并没有按退出的应用程序,切换到其他应用程序使我的应用程序进入后台待机模式,只要我方应用没有被杀死,当用户熄屏时,会启动OnepxActivity,这样人为的制造了一个系统欺骗,告诉ROM,用户执行熄屏时,当前UI是我的应用程序。这样,当用户亮屏时,因为有监听,OnepxActivity也会销毁,达到一个用户无感知同时又提高了我方的应用在第三方ROM中的存活率。

原创部分:

(1)前台服务器创建:

1,在前台服务器的创建(server.class):在类中,我创建了一个线程,是因为在像服务器做得到请求的时候,需要将程序放到线程中实现在onStartCommand函数中调用像素的广播。

包com.example.administrator.qshAndroid.web;


导入android.annotation.TargetApi;
导入android.app.Notification;
导入android.app.NotificationManager;
导入android.app.Service;
导入android.content.Context;
导入android.content.Intent;
导入android.content.IntentFilter;
导入android.os。*;
导入android.widget.Toast;
import com.example.administrator.demo.R;
import com.example.administrator.qshAndroid.utils.OnePixelReceiver;
import org.json.JSONException;
import org.json.JSONObject;

/ **
 *由管理员在2017年12月27日创建。
 * /
公共类服务器扩展服务{
    公共静态最终诠释NOTIFICATION_ID = 0x11;
    私人静态PowerManager.WakeLock mWakeLock;
    private String memberLoginBM =“”;
    private String getCode =“”;
    private OnePixelReceiver mOnepxReceiver;
    String infoBack =“”;
    int dataBack = 0;

    公共服务器(){
    }
    //必须实现的,绑定改服务时回调该方法
    @覆盖
    公共IBinder onBind(意图意图){
        抛出新的UnsupportedOperationException(“尚未实现”);
    }
    //服务器被创建时回调
    @覆盖
    public void onCreate(){
        // acquireWakeLock(本);
        super.onCreate();
    }
    //服务器断开连接时回调
    @覆盖
    public boolean onUnbind(Intent intent){
        Toast.makeText(server.this,“onUnbind!”,Toast.LENGTH_SHORT).show();
        返回true;
    }
    //服务器被关闭前回调
    @覆盖
    public void onDestroy(){
        stopForeground(true); //停止前台服务 - 参数:表示是否移除之前的通知
        Toast.makeText(server.this,“destory!”,Toast.LENGTH_SHORT).show();
        意图localIntent =新的意图();
        localIntent.setClass(this,server.class); //销毁时重新启动服务
        this.startService(localIntent);
    }
    @覆盖
    public void onRebind(Intent intent){
        Toast.makeText(server.this,“onRebind!”,Toast.LENGTH_SHORT).show();
        super.onRebind(意向);
    }
    @覆盖
    公共int onStartCommand(意图intent,诠释标志,诠释startId){
        //注册监听屏幕的广播,启动像素保活
        mOnepxReceiver = new OnePixelReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction( “android.intent.action.SCREEN_OFF”);
        intentFilter.addAction( “android.intent.action.SCREEN_ON”);
        intentFilter.addAction( “android.intent.action.USER_PRESENT”);
        registerReceiver(mOnepxReceiver,intentFilter);

        memberLoginBM = intent.getStringExtra(“allMessage”);
        getCode = intent.getStringExtra(“code”);
        new Thread(new MyThread2())。start();
        返回START_STICKY;
    }
    公共静态类InnerService延伸服务{
        @覆盖
        公共IBinder onBind(意图意图){
            返回null;
        }
        @覆盖
        public void onCreate(){
            super.onCreate();
            //发送与KeepLiveService中ID相同的通知,然后将其取消并取消自己的前台显示
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            builder.setContentTitle(“Foreground Service2”);
            builder.setContentText( “----------------------------”);
            startForeground(NOTIFICATION_ID,builder.build());
            new Handler()。postDelayed(new Runnable(){
                @覆盖
                public void run(){
                    stopForeground(真);
                    NotificationManager manager =(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
                    manager.cancel(NOTIFICATION_ID);
                    stopSelf();
                }
            },100);
        }
        @覆盖
        公共int onStartCommand(意图intent,诠释标志,诠释startId){
            //标记(TAG,“VMDaemonService-> onStartCommand”);
            / **
             *这里返回值是使用系统服务的机制自动重新启动,不过这种方式以下两种方式不适用:
             * 1.服务第一次被异常杀死后会在5秒内重启,第二次被杀死会在10秒内重启,第三次会在20秒内重启,一旦在短时间内服务被杀死达到5次,则系统不再拉起。
             * 2.进程被取得Root权限的管理工具或系统工具通过forestop停止掉,无法重启。
             * 3.一些定制化比较高的第三方系统也不适用
             * /
            返回START_STICKY;
        }
    }
    //子线程接收数据,主线程修改数据
    公共类MyThread2实现了Runnable {
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @覆盖
        public void run(){
                infoBack = serverPick.executeHttpGet(memberLoginBM,getCode);
                JSONObject jsonObject = null;
                尝试{
                    jsonObject = new JSONObject(infoBack);
                    dataBack = jsonObject.getInt(“success”);
                    Notification.Builder builder = new Notification.Builder(server.this);
                    引用代码= “1”;
                    if(dataBack == 1){
                        if(Build.VERSION.SDK_INT <18){
                            startForeground(NOTIFICATION_ID,new Notification()); // API <18,此方法能有效隐藏Notification上的图标
                        } else {
                            // API 18以上,发送通知并将其置为前台后,启动InnerService
                            builder.setSmallIcon(R.mipmap.ic_launcher);
                            //builder.setTicker("Foreground Service Start“);
                            builder.setContentTitle( “企商汇”);
                            builder.setContentText( “你有新的业务信息没有读取!”);
                            builder.setDefaults(Notification.DEFAULT_SOUND);
                            startForeground(NOTIFICATION_ID,builder.build());
                            startService(new Intent(server.this,InnerService.class));
                            了Thread.sleep(10000);
                            跑();
                            //继续;
                        }
                    } else if(dataBack == 2){
                        if(Build.VERSION.SDK_INT <18){
                            startForeground(NOTIFICATION_ID,new Notification()); // API <18,此方法能有效隐藏Notification上的图标
                        } else {
                            //Notification.Builder builder = new Notification.Builder(server.this);
                            builder.setSmallIcon(R.mipmap.ic_launcher);
                            //builder.setTicker("Foreground Service Start“);
                            builder.setContentTitle( “企商汇”);
                            builder.setContentText( “你暂时没有新的业务信息!”);
                            //builder.setDefaults(Notification.DEFAULT_SOUND);
                            startForeground(NOTIFICATION_ID,builder.build());
                            startService(new Intent(server.this,InnerService.class));
                            了Thread.sleep(10000);
                            跑();
                            // Toast.makeText(server.this,“你暂时没有新的业务信息!”,Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        if(Build.VERSION.SDK_INT <18){
                            startForeground(NOTIFICATION_ID,new Notification()); // API <18,此方法能有效隐藏Notification上的图标
                        } else {
                            builder.setSmallIcon(R.mipmap.ic_launcher);
                            //builder.setTicker("Foreground Service Start“);
                            builder.setContentTitle( “企商汇”);
                            builder.setContentText( “服务器,通讯错误,请重启应用程序!”);
                            //builder.setDefaults(Notification.DEFAULT_SOUND);
                            startForeground(NOTIFICATION_ID,builder.build());
                            startService(new Intent(server.this,InnerService.class));
                            了Thread.sleep(10000);
                            跑();
                        }
                    }
                catch(JSONException e){
                    e.printStackTrace();
                catch(InterruptedException e){
                    e.printStackTrace();
                }
        }
    }
}
2,在前台AndroidMainfest.xml文件中注册服务器

<service android:name =“com.example.administrator.qshAndroid.web.server”>
            <意图滤波器>
                <action android:name =“com.example.administrator.qshAndroid.web.server”/>
            </意图滤波器>
</服务>
3,在另一个活动中启动服务器

Intent intent2 = new Intent(menu.this,server.class);
intent2.putExtra( “allMessage”,allMessage);
intent2.putExtra( “代码”, “2”);
startService(intent2);
如图4所示,在1中创建的像素BroadcastReceiver.java

包com.example.administrator.qshAndroid.utils;

导入android.content.BroadcastReceiver;
导入android.content.Context;
导入android.content.Intent;
导入android.content.IntentFilter;

/ **
 *由管理员于2018-1-9创建。
 * /
公共类OnePixelReceiver扩展BroadcastReceiver {
    私人静态OnePixelReceiver接收器;
    @覆盖
    public void onReceive(Context context,Intent intent){
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {    //屏幕关闭启动1像素Activity
            Intent it = new Intent(context, OnePiexlActivity.class);
            it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(it);
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {   //屏幕打开 结束1像素
            context.sendBroadcast(new Intent("finish activity"));
        }
    }
    public static void register1pxReceiver(Context context) {
        if (receiver == null) {
            receiver = new OnePixelReceiver();
        }
        context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
        context.registerReceiver(receiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
    }

    public static void unregister1pxReceiver(Context context) {
        context.unregisterReceiver(receiver);
    }
}
5,像素的活性(OnePiexActivity.java)

包com.example.administrator.qshAndroid.utils;

导入android.app.Activity;
导入android.content.BroadcastReceiver;
导入android.content.Context;
导入android.content.Intent;
导入android.content.IntentFilter;
导入android.os.Bundle;
导入android.os.PowerManager;
导入android.view.Gravity;
导入android.view.Window;
导入android.view.WindowManager;

/ **
 *由管理员于2018-1-9创建。
 * /
公共类OnePiexlActivity扩展活动{
    私人BroadcastReceiver endReceiver;

    @覆盖
    保护无效的onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        //设置1个像素
        窗口窗口= getWindow();
        window.setGravity(Gravity.LEFT | Gravity.TOP);
        WindowManager.LayoutParams params = window.getAttributes();
        params.x = 0;
        params.y = 0;
        params.height = 1;
        params.width = 1;
        window.setAttributes(PARAMS);

        //结束该页面的广播
        endReceiver = new BroadcastReceiver(){
            @覆盖
            public void onReceive(Context context,Intent intent){
                完();
            }
        };
        registerReceiver(endReceiver,new IntentFilter(“finish”));
        //检查屏幕状态
        checkScreen();
    }

    @覆盖
    保护无效onResume(){
        super.onResume();
        checkScreen();
    }

    / **
     *检查屏幕状态isScreenOn为true屏幕“亮”结束该活动
     * /
    private void checkScreen(){
        PowerManager pm =(PowerManager)OnePiexlActivity.this.getSystemService(Context.POWER_SERVICE);
        boolean isScreenOn = pm.isScreenOn();
        if(isScreenOn){
            完();
        }
    }
}
如图6所示,设置像素为透明:

<style name =“OnePixelActivity”parent =“android:Theme.Holo.Light.NoActionBar”> //无标题
        <item name =“android:windowIsTranslucent”> true </ item> //透明
如图7所示,在XML注册中 OnePiexActivity.java
<activity android:name =“com.example.administrator.qshAndroid.utils.OnePiexlActivity”
                   机器人:screenOrientation = “画像”
                   机器人:主题= “@风格/ OnePixelActivity”> </活动>
逻辑流程:在主活动中,调用我们的前台服务器,在前台服务器中调用像素广播,像素广播调用像素的活动,这样在锁屏的时候,调用活动,开启的时候关闭即可就这样,恭喜。你,你的Android的被保活了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值