关于android双进程守护-后台持续定位功能+项目IM中写到自己的即时通讯

1.关于进程守护无非就是6.0以下,6.0以上的高版本保活

a.android中6.0以下的保护采用双线程守护即可是aidl

      (1)创建aidl文件

     interface IServiceAidlInterface {
        String getServiceName(); 
     }
  (2)创建本地service是LocalService类实现aidl接口
public class LocalService extends Service {
    MyBinder binder;
    MyConn conn;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        binder = new MyBinder();
        conn = new MyConn();
    }

    class MyBinder extends IServiceAidlInterface.Stub {
        @Override
        public String getServiceName() throws RemoteException {
            return LocalService.class.getSimpleName();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(LocalService.this, " 本地服务活了", Toast.LENGTH_SHORT).show();
        this.startService(new Intent(LocalService.this,RomoteService.class));
        this.bindService(new Intent(LocalService.this,RomoteService.class),conn, Context.BIND_IMPORTANT);
        return START_STICKY;
    }

    class MyConn implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("box", "绑定上了远程服务");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("box", "远程服务被干掉了");
            Toast.makeText(LocalService.this, "远程服务挂了", Toast.LENGTH_SHORT).show();
            //开启远程服务
            LocalService.this.startService(new Intent(LocalService.this,RomoteService.class));
            //绑定远程服务
            LocalService.this.bindService(new Intent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //开启远程服务
        LocalService.this.startService(new Intent(LocalService.this,RomoteService.class));
        //绑定远程服务
        LocalService.this.bindService(new Intent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);

    }

    private void show() {
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Toast.makeText(LocalService.this, "本地服务正常", Toast.LENGTH_SHORT).show();
                super.handleMessage(msg);
            }
        };

        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);
            }
        };
        timer.schedule(task, 2000, 2000);
    }

}

(3)创建一个RomoteService服务分别实现aidl接口的调用

public class RomoteService extends Service{
    MyConn conn;
    MyBinder binder;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        conn = new MyConn();
        binder = new MyBinder();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        show();
        Toast.makeText(this, " 远程服务活了", Toast.LENGTH_SHORT).show();
        this.bindService(new Intent(this, LocalService.class), conn, Context.BIND_IMPORTANT);
        return START_STICKY;
    }
    class MyBinder extends IServiceAidlInterface.Stub {
        @Override
        public String getServiceName() throws RemoteException {
            return RomoteService.class.getSimpleName();
        }
    }
    class MyConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("box", "绑定本地服务成功");
            // Toast.makeText(RomoteService.this, "绑定本地服务成功", Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("box", "本地服务被干掉了");
            Toast.makeText(RomoteService.this, "本地服务挂了", Toast.LENGTH_SHORT).show();

            //开启本地服务
            RomoteService.this.startService(new Intent(RomoteService.this, LocalService.class));
            //绑定本地服务
            RomoteService.this.bindService(new Intent(RomoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //开启本地服务
        RomoteService.this.startService(new Intent(RomoteService.this, LocalService.class));
        //绑定本地服务
        RomoteService.this.bindService(new Intent(RomoteService.this, LocalService.class), conn,Context.BIND_IMPORTANT);
    }
    private void show() {
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Toast.makeText(RomoteService.this, "远程服务正常", Toast.LENGTH_SHORT).show();
                super.handleMessage(msg);
            }
        };

        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Message message = new Message();
                message.what = 1;
                handler.sendMessage(message);
            }
        };
        timer.schedule(task, 2000, 2000);
    }
}

(4)可以监听系统的某些动作来实现监听,判断LocalService和RomoteService是否还在进行,这儿我写了一个工具类判断当前服务是否还在进行和判断当前包名是否也还在进行当中

/**
 * 判断本应用是否存活
 * 如果需要判断本应用是否在后台还是前台用getRunningTask
 */
public static boolean isAPPALive(Context mContext, String packageName) {
    boolean isAPPRunning = false;
    // 获取activity管理对象
    ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
    // 获取所有正在运行的app
    List<ActivityManager.RunningAppProcessInfo> appProcessInfoList = activityManager.getRunningAppProcesses();
    // 遍历,进程名即包名
    for (ActivityManager.RunningAppProcessInfo appInfo : appProcessInfoList) {
        if (packageName.equals(appInfo.processName)) {
            isAPPRunning = true;
            break;
        }
    }
    return isAPPRunning;
}

 

/**
 * 判断某个服务是否正在运行的方法
 *
 * @param serviceName 是包名+服务的类名(例如:net.loonggg.testbackstage.TestService)
 * @return true代表正在运行,false代表服务没有正在运行
 */
public static boolean serviceAlive(Context context, String serviceName) {
    boolean isWork = false;
    ActivityManager myAM = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningServiceInfo> myList = myAM.getRunningServices(100);
    if (myList.size() <= 0) {
        return false;
    }
    for (int i = 0; i < myList.size(); i++) {
        String mName = myList.get(i).service.getClassName().toString();
        if (mName.equals(serviceName)) {
            isWork = true;
            break;
        }
    }
    return isWork;
}

(5).可以创建单个的1像素Activity在页面监听

public class SinglePixelActivity extends AppCompatActivity {
    private static final String TAG = "SinglePixelActivity";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate--->启动1像素保活");
        Window mWindow = getWindow();
        mWindow.setGravity(Gravity.LEFT | Gravity.TOP);
        WindowManager.LayoutParams attrParams = mWindow.getAttributes();
        attrParams.x = 0;
        attrParams.y = 0;
        attrParams.height = 300;
        attrParams.width = 300;
        mWindow.setAttributes(attrParams);
        // 绑定SinglePixelActivity到ScreenManager
        ScreenManager.getScreenManagerInstance(this).setSingleActivity(this);
    }
锁屏工具类
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);
    }
    public  class SreenBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.d("KeepAppAlive","SreenLockReceiver-->监听到系统广播:"+action);
            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();
            }
        }
    }
   // 监听sreen状态对外回调接口
    public interface SreenStateListener {
        void onSreenOn();
        void onSreenOff();
        void onUserPresent();
    }
}

2.针对于android中7.0以上的手机采用jobservice

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class JobWakeUpService extends JobService {
    private int JobWakeUpId = 1;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //开启轮寻
        JobInfo.Builder mJobBulider = new JobInfo.Builder(
                JobWakeUpId, new ComponentName(this, JobWakeUpService.class));

//        //设置轮寻时间
        mJobBulider.setPeriodic(15 * 60 * 1000);
        //系统当你的设备重启之后你的任务是否还要继续执行
        mJobBulider.setPersisted(true);  // 设置设备重启时,执行该任务
        mJobBulider.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
        mJobBulider.setRequiresCharging(true); // 当插入充电器,执行该任务
        JobScheduler mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        JobInfo info = mJobBulider.build();
        mJobScheduler.schedule(info); //开始定时执行该系统任务
        return START_STICKY;
    }

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
         Log.e("aa", "-----------onStartJob-------");
        //开启定时任务 定时轮寻 判断应用Service是否被杀死
        //如果被杀死则重启Service
        mJobHandler.sendMessage(Message.obtain(mJobHandler, 1, jobParameters));
        return false;
    }


    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        Log.e("aa", "-----------onStopJob-------");
        mJobHandler.removeMessages(1);
        return true;
    }

    private Handler mJobHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {

                  //这儿是列举的获取数据这样传递值过去的

           Intent intent = new Intent();
          intent.putExtra(AppHawkey.LONGITUDE_KEY, longitude);
          intent.putExtra(AppHawkey.LATITUDE_KEY, latitude);
          LocationService.enqueueWork(getApplicationContext(), intent);
            jobFinished((JobParameters) msg.obj, false);
            return true;
        }

    });

对了针对于上面的你在service中获取的数据最好是用JobIntentService,具体原因是抛了一个错误,crash

       java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.xxx.xx/.core.service.NotifyJobService }: app is in background uid UidRecord{6dd5849 u0a172 TPSL idle change:idle|cached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1628)
at android.app.ContextImpl.startService(ContextImpl.java:1569)
at android.content.ContextWrapper.startService(ContextWrapper.java:675)
at com.xxx.xx.application.MainApp.onCreate(Unknown Source:385)
at com.baidu.protect.A.a(Native Method)
at com.baidu.protect.StubApplication.onCreate(StubApplication.java:296)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1154)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6273) ... 8 more

 在android系统8.0以上适配请添加以下权限

使用示例:
1.在Manifest中声名Permission:
<uses-permission android:name="android.permission.WAKE_LOCK" />
2.在Manifest中声名Service:

<service android:name=".service.LocationService"
    android:permission="android.permission.BIND_JOB_SERVICE"
   />  


3.实现JobIntentService类:

 

public class LocationService extends JobIntentService {
    /**
     * 这个Service 唯一的id
     */
    static final int JOB_ID = 10111;


    /**
     * Convenience method for enqueuing work in to this service.
     */
    static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, LocationService.class, JOB_ID, work);
        LocationUtil.isOpen=true;
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        double longitude = intent.getDoubleExtra(AppHawkey.LONGITUDE_KEY, 0.00);
        double latitude = intent.getDoubleExtra(AppHawkey.LATITUDE_KEY, 0.00);
        LogUtil.e("-------longitude------" + longitude);
        LogUtil.e("-------latitude------" + latitude);
        String locationKey = PreferenceUtils.getString(AppHawkey.LOCATION_SAVE_KEY, "");
        if (!TextUtils.isEmpty(locationKey)) {
            UploadLoaction loaction = JsonUtil.fromJson(locationKey, UploadLoaction.class);
            if (loaction.getLocations() != null && loaction != null) {
                List<UploadLoaction.location> data = new ArrayList<>();
                data.addAll(loaction.getLocations());
                UploadLoaction.location item = new UploadLoaction.location();
                item.setLongitude(longitude);
                item.setLatitude(latitude);

                data.add(item);
                loaction.setLocations(data);
                String toJson = JsonUtil.toJson(loaction);
                toast(toJson);
                PreferenceUtils.setString(AppHawkey.LOCATION_SAVE_KEY, toJson);

            }
        } else {
            UploadLoaction loaction = new UploadLoaction();
            List<UploadLoaction.location> data = new ArrayList<>();

            UploadLoaction.location item = new UploadLoaction.location();
            item.setLatitude(latitude);
            item.setLongitude(longitude);

            data.add(item);
            loaction.setLocations(data);

            String toJson = JsonUtil.toJson(loaction);
            toast(toJson);
            PreferenceUtils.setString(AppHawkey.LOCATION_SAVE_KEY, toJson);
        }

    }

    final Handler mHandler = new Handler();

    // Helper for showing tests
    void toast(final CharSequence text) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(LocationService.this, text, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值