1. 程式人生 > >Android 省電開發之 JobSchedule

Android 省電開發之 JobSchedule

android的電量一直是所有人關注的問題,

電池越來越大,使用起來沒有任何改善,有人覺得是螢幕越來越大導致的,但是實際上更多的是app的不注意,導致的浪費了很多電量。

從本章開始,我們將從開發的角度來告訴大家,如何使我們的應用更加省電的一些技巧。

JobSchedule

這個是Android 5.0之後,考慮到截止我寫這篇文章的時候,Android 5.0以上的使用者已經增加到25.1%,我覺的在開發中,建議使用JobSchedule來規範我們的開發。

功能:JobSchedule的作用就是將我們需要定時或者特定條件的事件交給系統,當系統滿足條件的時候,就會回撥我們的元件,執行我們的程式碼,並且在執行的過程中會回撥我們的方法,

條件:在剛剛我說了在特定條件,這個當然不是隨便的條件,而是規定好的,(我總結了4+1種條件)

條件1:網路可用

網路可用還可以分為兩種 一種是網路可用,任何網路都會觸發工作 另一種只有不限制流量的網路觸發,這個可以認為是wifi觸發

條件2:定時

這個是與其他條件組合使用的,更趨近於deadline的概念,如果在規定時間內,沒有任何條件發生,則執行工作

條件3:手機處於空閒狀態

裝置處於螢幕關閉或dreaming狀態(類似window的休眠動畫狀態)71分鐘後,執行工作

條件4:手機是否處於供電穩定狀態(充電)

這個也並非只是插入充電器,而且還要在電池處於健康狀態的情況下才會觸發,一般來說是手機電量

>15%

條件+1:迴圈執行(被列入+1是因為這個需要前四個觸發之後才有用處,當然你也可以把它歸為定時

這個不是某種條件,但可以設定為迴圈執行方式,即任何條件滿足之後,間隔指定時間仍會執行

使用方法:

        ComponentName mServiceComponent = new ComponentName(this, TestJobService.class);           //當事件滿足的時候,呼叫的元件
        JobInfo.Builder builder = new JobInfo.Builder(i, mServiceComponent);                       //i為int值,當前事件的
        JobScheduler tm =(JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.schedule(builder);
這裡只是一個使用的最小模型,他並不會有任何的觸發條件,因為我們還沒有新增,(這只是例子啊,你如果真的這麼寫,直接就丟擲異常了,因為不允許不設定任何條件,這樣沒意義)

下面依次對每一種觸發進行設定:

網路觸發:

builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);                //設定為不限制流量的條件觸發,可以認為是wifi條件下觸發
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);                                 //有網路連線的時候觸發

定時:

builder.setOverrideDeadline(time); //其實這裡與我們所想的用法又有所區別,他並沒有單獨提供介面,而是複用,這個方法在後面有另一種用法的介紹。

手機處於空閒狀態:

builder.setRequiresDeviceIdle(true/*false*/);                                                                          //設定為空閒狀態觸發

手機是否處於供電穩定狀態

builder.setRequiresCharging(true/*false*/);                                                                           //手機是否處於充電狀態

除了這些條件之外還可以進行一些其他的設定來控制觸發狀態

builder.setMinimumLatency(time);                                                                                          //time的單位是s,作用是滿足觸發條件也要延時time 豪秒之後再觸發

builder.setOverrideDeadline(time);                                                                                        //time的單位是s,作用是設定time豪秒之後,如果沒有任何觸發也執行

builder.setPeriodic(time);                                                                                                         //設定迴圈觸發,否則觸發一次就結束了,這樣可以間隔time豪秒之後,還是可以觸發

builder.setPersisted(true/*false*/);                               //設定觸發條件是否重啟手機後仍有效。         /這個它是通過將presist的資訊,寫到了/data/system/job/jobs.xml檔案中了

builder.setExtras(PersistableBundle extra);                     //設定startJob時,帶有Bundle

builder.setBackoffCriteria(Long.valueOf(backoffTime) * 1000, backoffPolicy);           //這個是比較特殊的,這個是當意外發生的時候,多久之後,重新執行,分為線性計算和指數計算,
綜上就是JobSchedule的基本使用方法,
下面我來展示一下Google所給的官方示例:
/*
 * Copyright 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.jobscheduler.service;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import com.example.android.jobscheduler.MainActivity;

import java.util.LinkedList;


/**
 * Service to handle callbacks from the JobScheduler. Requests scheduled with the JobScheduler
 * ultimately land on this service's "onStartJob" method. Currently all this does is post a message
 * to the app's main activity to change the state of the UI.
 */
public class TestJobService extends JobService {
    private static final String TAG = "SyncService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service created");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Service destroyed");
    }

    /**
     * When the app's MainActivity is created, it starts this service. This is so that the
     * activity and this service can communicate back and forth. See "setUiCalback()"
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Messenger callback = intent.getParcelableExtra("messenger");
        Message m = Message.obtain();
        m.what = MainActivity.MSG_SERVICE_OBJ;
        m.obj = this;
        try {
            callback.send(m);
        } catch (RemoteException e) {
            Log.e(TAG, "Error passing service object back to activity.");
        }
        return START_NOT_STICKY;
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        // We don't do any real 'work' in this sample app. All we'll
        // do is track which jobs have landed on our service, and
        // update the UI accordingly.
        jobParamsMap.add(params);
        if (mActivity != null) {
            mActivity.onReceivedStartJob(params);
        }
        Log.i(TAG, "on start job: " + params.getJobId());
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        // Stop tracking these job parameters, as we've 'finished' executing.
        jobParamsMap.remove(params);
        if (mActivity != null) {
            mActivity.onReceivedStopJob();
        }
        Log.i(TAG, "on stop job: " + params.getJobId());
        return true;
    }

    MainActivity mActivity;
    private final LinkedList<JobParameters> jobParamsMap = new LinkedList<JobParameters>();

    public void setUiCallback(MainActivity activity) {
        mActivity = activity;
    }

    /** Send job to the JobScheduler. */
    public void scheduleJob(JobInfo t) {
        Log.d(TAG, "Scheduling job");
        JobScheduler tm =
                (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.schedule(t);
    }

    /**
     * Not currently used, but as an exercise you can hook this
     * up to a button in the UI to finish a job that has landed
     * in onStartJob().
     */
    public boolean callJobFinished() {
        JobParameters params = jobParamsMap.poll();
        if (params == null) {
            return false;
        } else {
            jobFinished(params, false);
            return true;
        }
    }

}
/*
 * Copyright 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.jobscheduler;

import android.app.Activity;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;

import com.example.android.jobscheduler.service.TestJobService;

public class MainActivity extends Activity {

    private static final String TAG = "MainActivity";

    public static final int MSG_UNCOLOUR_START = 0;
    public static final int MSG_UNCOLOUR_STOP = 1;
    public static final int MSG_SERVICE_OBJ = 2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_main);
        Resources res = getResources();
        defaultColor = res.getColor(R.color.none_received);
        startJobColor = res.getColor(R.color.start_received);
        stopJobColor = res.getColor(R.color.stop_received);

        // Set up UI.
        mShowStartView = (TextView) findViewById(R.id.onstart_textview);
        mShowStopView = (TextView) findViewById(R.id.onstop_textview);
        mParamsTextView = (TextView) findViewById(R.id.task_params);
        mDelayEditText = (EditText) findViewById(R.id.delay_time);
        mDeadlineEditText = (EditText) findViewById(R.id.deadline_time);
        mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered);
        mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any);
        mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging);
        mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle);
        mServiceComponent = new ComponentName(this, TestJobService.class);
        // Start service and provide it a way to communicate with us.
        Intent startServiceIntent = new Intent(this, TestJobService.class);
        startServiceIntent.putExtra("messenger", new Messenger(mHandler));
        startService(startServiceIntent);
    }
    // UI fields.
    int defaultColor;
    int startJobColor;
    int stopJobColor;

    private TextView mShowStartView;
    private TextView mShowStopView;
    private TextView mParamsTextView;
    private EditText mDelayEditText;
    private EditText mDeadlineEditText;
    private RadioButton mWiFiConnectivityRadioButton;
    private RadioButton mAnyConnectivityRadioButton;
    private CheckBox mRequiresChargingCheckBox;
    private CheckBox mRequiresIdleCheckbox;

    ComponentName mServiceComponent;
    /** Service object to interact scheduled jobs. */
    TestJobService mTestService;

    private static int kJobId = 0;

    Handler mHandler = new Handler(/* default looper */) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UNCOLOUR_START:
                    mShowStartView.setBackgroundColor(defaultColor);
                    break;
                case MSG_UNCOLOUR_STOP:
                    mShowStopView.setBackgroundColor(defaultColor);
                    break;
                case MSG_SERVICE_OBJ:
                    mTestService = (TestJobService) msg.obj;
                    mTestService.setUiCallback(MainActivity.this);
            }
        }
    };

    private boolean ensureTestService() {
        if (mTestService == null) {
            Toast.makeText(MainActivity.this, "Service null, never got callback?",
                    Toast.LENGTH_SHORT).show();
            return false;
        }
        return true;
    }

    /**
     * UI onclick listener to schedule a job. What this job is is defined in
     * TestJobService#scheduleJob().
     */
    public void scheduleJob(View v) {
        if (!ensureTestService()) {
            return;
        }

        JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent);

        String delay = mDelayEditText.getText().toString();
        if (delay != null && !TextUtils.isEmpty(delay)) {
            builder.setMinimumLatency(Long.valueOf(delay) * 1000);
        }
        String deadline = mDeadlineEditText.getText().toString();
        if (deadline != null && !TextUtils.isEmpty(deadline)) {
            builder.setOverrideDeadline(Long.valueOf(deadline) * 1000);
        }
        boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked();
        boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked();
        if (requiresUnmetered) {
            builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
        } else if (requiresAnyConnectivity) {
            builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
        }
        builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked());
        builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked());

        mTestService.scheduleJob(builder.build());

    }

    public void cancelAllJobs(View v) {
        JobScheduler tm =
                (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        tm.cancelAll();
    }

    /**
     * UI onclick listener to call jobFinished() in our service.
     */
    public void finishJob(View v) {
        if (!ensureTestService()) {
            return;
        }
        mTestService.callJobFinished();
        mParamsTextView.setText("");
    }

    /**
     * Receives callback from the service when a job has landed
     * on the app. Colours the UI and post a message to
     * uncolour it after a second.
     */
    public void onReceivedStartJob(JobParameters params) {
        mShowStartView.setBackgroundColor(startJobColor);
        Message m = Message.obtain(mHandler, MSG_UNCOLOUR_START);
        mHandler.sendMessageDelayed(m, 1000L); // uncolour in 1 second.
        mParamsTextView.setText("Executing: " + params.getJobId() + " " + params.getExtras());
    }

    /**
     * Receives callback from the service when a job that
     * previously landed on the app must stop executing.
     * Colours the UI and post a message to uncolour it after a
     * second.
     */
    public void onReceivedStopJob() {
        mShowStopView.setBackgroundColor(stopJobColor);
        Message m = Message.obtain(mHandler, MSG_UNCOLOUR_STOP);
        mHandler.sendMessageDelayed(m, 2000L); // uncolour in 1 second.
        mParamsTextView.setText("");
    }
}



相關推薦

Android 開發 JobSchedule

android的電量一直是所有人關注的問題, 電池越來越大,使用起來沒有任何改善,有人覺得是螢幕越來越大導致的,但是實際上更多的是app的不注意,導致的浪費了很多電量。 從本章開始,我們將從開發的角度來告訴大家,如何使我們的應用更加省電的一些技巧。 JobSchedule

一.Android開發效能優化

  電量優化 Android應用開發中的網路、定位、感測器等都是比較耗電的特性,我們應該正確使用API來有效降低應

Android基礎——快速開發定制BaseTemplate

temp .net fonts The 成了 抽取 一份 應該 我們 初學者肯定會遇到一個日常任務,那麽就是findViewById,setOnClickListener(暫且把它們稱為日常任務),而且很多人會把他們混在一起,導致項目結構混亂,最主要的是寫多了會煩,不覺得嗎

Android基礎——快速開發打造萬能適配器

臃腫 log 思想 代碼分析 htm 考試報名 做了 順序 基礎 這裏以ListView作演示,對於ListView我們再熟悉不過了,其步驟分為: 創建ListView的Bean對象 創建ListView的Adapter的ItemView布局 創建ListView的Ada

android軟件開發仿淘寶選擇規格的實現

per con attribute back view.gone boolean 做了 over ear 在一些app開發項目中選擇商品規格這個功能最容易遇到問題,想要實現需要的全部功能,但一直沒有成功,所以就去找了個Demo,學習界面UI采用recyclerview,it

Android USB Host開發manager.getDeviceList()獲取不到裝置列表【轉載】

原文:https://www.2cto.com/kf/201305/211304.html 同樣遇到這樣的問題,我的Android裝置是原道N12C,官方的4.0.3系統,遇到這個問題,後來找了半天找到的,現在彙總一下吧: 1、建立 android.hardware.usb.h

Android流媒體開發路一:Camera2採集攝像頭原始資料並手動預覽

Android Camera2採集攝像頭原始資料並手動預覽 最近研究了一下android攝像頭開發相關的技術,也看了Google提供的Camera2Basic呼叫示例,以及網上一部分程式碼,但都是在TextureView等預覽基礎上實現,而我想要做的是在不預覽的情況下,能獲取到攝

Android藍芽開發低功耗藍芽(藍芽4.0)開發全記錄

主要內容概況 前面我記錄了開發藍芽2.0的過程,今天準備介紹現在的主流藍芽技術,藍芽4.0的開發,該藍芽技術是在Android4.3(API級別18)版本引入的API。 官方文件 具體的區別主要以下幾點: 1.新的藍芽技術提供了連線服務的方法,以前是沒有提供連線藍芽的方法

Android藍芽開發經典藍芽(藍芽2.0)開發全記錄

前言部分 最近因為需要開始藍芽相關開發,所以在網上搜索了很多內容,並且結合自己的開發過程做了一個總結,先儲備上,也許可能幫到正在做藍芽開發的同學。 藍芽很早就是android裝置上基本通訊功能了,只是以前的沒有那麼多藍芽裝置,現在藍芽裝置種類繁多,所以經常會有人遇到藍芽相關的開發

Android外掛化開發AMS與應用程式(客戶端ActivityThread、Instrumentation、Activity)通訊模型分析

今天主要分析下ActivityManagerService(服務端) 與應用程式(客戶端)之間的通訊模型,在介紹這個通訊模型的基礎上,再    簡單介紹實現這個模型所需要資料型別。         本文所介紹內容基於android2.2版本。由於Android版本的不同

Android 藍芽開發搜尋、配對、連線、通訊大全

        藍芽( Bluetooth®):是一種無線技術標準,可實現固定裝置、移動裝置和樓宇個人域網之間的短距離資料交換(使用2.4—2.485GHz的ISM波段的UHF無線電波)。藍芽裝置最多可以同時和7個其它藍芽裝置建立連線,進行通訊,當然並不是每一個藍芽都可以達到

Android Unity3D遊戲開發躲避方塊

開發環境 Window 7 Unity3D 3.4 MB525 defy  Android 2.1-update1        羽化的第四篇部落格,這次給大家送上自己初學Unity時寫的一個小遊戲Demo,我叫它“躲避方塊”,其實這個遊戲可以無限擴充套件,可以做成聯機

Android下jni開發ndk的使用(下載、配置、編譯遇到的問題)

Android下jni開發之ndk的使用 一、簡介      JNI和NDK很多Android開發初學者沒有搞明白這個問題,JNI是Java呼叫Native機制,是Java語言自己的特性全稱為Java Native Interface,類似的還

android ReactNative混合開發最新教程

參考官方文件->react native 文件 本文使用開發環境 Android studio 注意最新的react native支援的最新的SDK為16(android4.1) 建立Android專案(已有專案跳過) 開啟Android studio 輸入專案名稱,選擇專案目錄,點選nex

ArcGIS Android API 應用開發圖形繪製與長度面積量算

本文通過一個簡單的小Demo,向大家介紹如何使用ArcGIS Android API繪製點、線、面圖形,並且測量線的長度和多邊形的面積。 首先來看一下程式執行的效果圖: 實現上述功能,首先需要向地圖中新增一個GraphicsLayer,用來繪製Point、Poly

Android策略及測試

1、電源測試----------------------------------------------------1)檢視電源狀態:adb shell dumpsys batteryCurrent Battery Service state:  (UPDATES STOPP

android+unity3D遊戲開發音效播放

                音效讓我們的遊戲更逼真,更有情調,呵呵,今天我們來播放一首賽車加速的音效吧。 首先先把我們的賽車音效加入到工程裡面(這個會吧,直接拖進去就行了); 然後就是新建一個javascript文字,指令碼程式碼如下: var oldboy:Audio

Android】Adroid開發判斷一個自己的apk是否已經簽名

今天給大家帶來一個知識點,那就是判斷自己的android應用apk是否進行了簽名。我這裡是用的Windows 測試。首先,進入我們的jdk的安裝目錄。如這裡是我的:D:\Users\kaifagongju\Java\jdk1.7.0_79\bin 然後,

Android控制元件開發Gallery3D酷炫效果 瀏覽圖片

效果網上已經很多人做出來了,只是這次需要用到,所以自己也實踐了一下(這裡例子我也是根據網上一些資料編寫)。特下面針對一些關鍵程式碼進行簡要說明,需要做這方面東西的朋友可以看看。這篇文章是實用性文章,理論分析不多。

Android樣式的開發drawable

0 概述 res/drawable目錄下是Android用來存放圖片資原始檔的路徑。這裡除了有常規的圖片外,還支援selector/shape等定製或自定義圖片。 資源命名規則 下面將詳細分析: 1.1 StateListDrawable