Android 應用進程防殺指南 3-JobService

在前兩篇博客中,咱們系統的學習了Android應用進程防殺套路和雙進程守護的實現,不懂的童鞋們請查看 Android應用進程防殺指南1-經常使用套路 和 Android應用進程防殺指南2-雙進程守護兩篇博文。java

本篇博文,我將帶領你們學習更高端的APP進行防殺技巧,該技巧除了可以應對衛士、管家的清殺之外,更可以在相似於某米、某爲系統的清理內存軟件清理下確保進程存活下來。它就是咱們今天的主角JobShedulerService。android

一般在5.0以前,咱們可使用廣播或者鬧鐘等方式讓咱們的進程防殺自啓,而5.0之後的Android系統,咱們就可使用JobService,JobService它是Android5.0之後新增的一個服務。網絡

Google從Android SDK 21以後添加了JobScheduler來執行一些知足特定條件但不緊急的後臺任務,咱們能夠利用JobScheduler來執行這些特殊的後臺任務時來減小電量的消耗。JobService則是一個抽象類,其中包含兩個抽象方法:app

abstract boolean onStartJob(JobParameters params)
// 咱們須要重寫onStartJob方法在JobService被調度的時候
abstract boolean onStopJob(JobParameters params)
// 若是肯定中止系統調度做業,即便調度做業可能被完成,將調用此方法

當咱們有如下需求時,可使用調度做業ide

  • APP有能夠推遲的非面向用戶的工做
  • APP有當插入設備時您但願優先執行的工做
  • APP有須要訪問網絡或 Wi-Fi 鏈接的任務
  • APP有但願做爲一個批次按期運行的許多任務

接下來,咱們使用JobService來實現APP進程防殺。學習

1.首先聲明權限

(球球備註:若是不聲明jobshedul會報錯,若是第一次裝app的時候沒有這個permission,之後uid會有cache,再加上這個permission的app依然沒有這個permission。因此可能會要求app的用戶卸載從新安裝一下才能生效。service的android.permission.BIND_JOB_SERVICE也要加。)ui

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.jpush.app1"   
    android:versionCode="301"
    android:versionName="3.0.1"
    >
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 <!--省略其餘的-->
 <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:name="com.example.jpushdemo.ExampleApplication">
 <!--省略其餘的-->
    <service
            android:name="com.example.jpushdemo.JobCastielService"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE">
        </service>
    </application>
</manifest>

2.自定義一個Service類,繼承自JobService

/**
 * 
* @ClassName: JobCastielService 
* @Description: 自定義 JobService
* @author 猴子搬來的救兵 http://blog.csdn.net/mynameishuangshuai
* @version
 */
@SuppressLint("NewApi")
public class JobCastielService extends JobService{
    private int kJobId = 0;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("castiel", "jobService啓動");
        scheduleJob(getJobInfo());
        return START_NOT_STICKY;
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.i("castiel", "執行了onStartJob方法");
        boolean isLocalServiceWork = isServiceWork(this, "com.castiel.service.LocalCastielService");
        boolean isRemoteServiceWork = isServiceWork(this, "com.castiel.service.RemoteCastielService");
        if(!isLocalServiceWork||
           !isRemoteServiceWork){
            this.startService(new Intent(this,LocalCastielService.class));
            this.startService(new Intent(this,RemoteCastielService.class));
            Toast.makeText(this, "進程啓動", Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.i("castiel", "執行了onStopJob方法");
        scheduleJob(getJobInfo());
        return true;
    }

    //將任務做業發送到做業調度中去
    public void scheduleJob(JobInfo t) {
        Log.i("castiel", "調度job");
        JobScheduler tm =
                (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.schedule(t);
    }

    public JobInfo getJobInfo(){
        JobInfo.Builder builder = new JobInfo.Builder(kJobId++, new ComponentName(this, JobCastielService.class));
        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
        builder.setPersisted(true);
        builder.setRequiresCharging(false);
        builder.setRequiresDeviceIdle(false);
        //間隔100毫秒
        builder.setPeriodic(100);
        return builder.build();
    }


    // 判斷服務是否正在運行
    public boolean isServiceWork(Context mContext, String serviceName) {  
        boolean isWork = false;  
        ActivityManager myAM = (ActivityManager) mContext  
                .getSystemService(Context.ACTIVITY_SERVICE);  
        List<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.0以上的設備必需要把app設置爲自啓動,若是系統沒給自啓動,是啓動不了的。每種手機都有本身的設置位置。還有一個問題就是,若是強停停了5次以上,好像就啓動不了了。)this

相關文章
相關標籤/搜索