王学岗性能优化9——电量优化

第一:电量和网络状态的监控
因为本章涉及到粘性广播,所以我这里有介绍下粘性广播的一篇文章粘性广播
Battery类

package com.example.administrator.lsn_9_demo;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryManager;

/**
 * 主动得到充电状态和网络状态
 */
public class Battery {
    /**
     * 是否在充电
     */
    public static boolean isPlugged(Context context){
        //1,发送一个包含充电状态的广播,并用粘性广播、
		//2,电量发生改变的一个广播
        IntentFilter filter=new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent intent = context.registerReceiver(null, filter);
        //获取充电状态,-1为默认值
        int isPlugged=intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,-1);
        //电源充电
        boolean acPlugged=isPlugged==BatteryManager.BATTERY_PLUGGED_AC;
        boolean usbPlugged=isPlugged==BatteryManager.BATTERY_PLUGGED_USB;
		//无线充电
        boolean wrieliessPlugged=isPlugged==BatteryManager.BATTERY_PLUGGED_WIRELESS;
        
        return acPlugged || usbPlugged || wrieliessPlugged;
    }

    /**
     * 是否在使用wifi
     */
    public static boolean isWifi(Context context){
        ConnectivityManager cm=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //获取当前活动的网络信息
        NetworkInfo activeNetworkInfo=cm.getActiveNetworkInfo();
		//活动信息是存在的;是否断网;是不是wifi
        if(null!=activeNetworkInfo && activeNetworkInfo.isConnected()
                && activeNetworkInfo.getType()==ConnectivityManager.TYPE_WIFI){
            return true;
        }
        return false;
    }
}

以上代码可以判断网络存在还是不存在,以及充电状态。这种方法时主动通过代码来访问的,还有一种方式就是我们可以通过广播来处理。当我们开始充电或者切换网络的时候,系统本身也会发送一个广播,
注册电源广播

 <receiver android:name=".PowerConnectionReceiver">
            <intent-filter>
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
            </intent-filter>

WiFi广播

 <receiver android:name=".WifiConnectionReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
            </intent-filter>
        </receiver>
package com.dongnao.battery;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

/**
 * 被动获取是否wifi
 */

public class WifiConnectionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Battery.isWifi(context)){
            Log.i("WIFI","当前正在使用wifi");
            Toast.makeText(context,"当前正在使用wifi",Toast.LENGTH_SHORT).show();
        } else{
            Log.i("WIFI","当前不正在使用wifi");
            Toast.makeText(context,"当前不在使用wifi",Toast.LENGTH_SHORT).show();
        }
    }
}

package com.dongnao.battery;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.widget.Toast;

/**
 *  被动接收充电状态,收到广播之后就知道是否在充电了
 */
public class PowerConnectionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (TextUtils.equals(action,Intent.ACTION_POWER_CONNECTED)){
            Toast.makeText(context,"当前正在充电",Toast.LENGTH_SHORT).show();
        } else if(TextUtils.equals(action,Intent.ACTION_POWER_DISCONNECTED)){
            Toast.makeText(context,"当前不在充电",Toast.LENGTH_SHORT).show();
        }
    }
}

第二:解决即时性很高的需求,以高德地图为例
解决即时性很高的需求,比如股票软件,时时刻刻会接受信息,再比如地图,要不断收集信息,本例子中就是每隔五秒,就会有
一个地理信息发过来。
我们这里有个LocationManager类,具体的定位类,完全是仿照高德地图写的,没什么可以讲的,

package com.dongnao.battery.location;

import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.dongnao.battery.JobManager;


public class LocationManager {
    //声明AMapLocationClient类对象
    private AMapLocationClient mLocationClient;

    private static LocationManager instance;

    private Context applicationContext;

    public LocationManager() {

    }

    public static LocationManager getInstance() {
        if (null == instance) {
            instance = new LocationManager();
        }
        return instance;
    }

    //1,声明定位回调监听器,
    //2,如果位置发生改变,会把aMapLocation地址传过来
    //传过来之后会调用  ,UploadService.UploadLocation(applicationContext, location);把位置信息上传到
    //服务器
    public AMapLocationListener mLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            if (aMapLocation != null) {
                if (aMapLocation.getErrorCode() == 0) {
                    //获得json
                    String location = aMapLocation.toStr();
                    //启动IntentService 上传坐标数据
                    // 主要不是实时需要的,延迟执行
                   UploadService.UploadLocation(applicationContext, location);
                 
                } else {
                    //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
                    Log.e("AmapError", "location Error, ErrCode:"
                            + aMapLocation.getErrorCode() + ", errInfo:"
                            + aMapLocation.getErrorInfo());
                }
            }
        }
    };

    public void startLocation(Context context) {
        if (null != mLocationClient) {
            mLocationClient.startLocation();
            return;
        }
        applicationContext = context.getApplicationContext();
        //初始化定位
        mLocationClient = new AMapLocationClient(applicationContext);
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener);
        //声明AMapLocationClientOption对象
        AMapLocationClientOption mLocationOption = null;
        //初始化AMapLocationClientOption对象
        mLocationOption = new AMapLocationClientOption();
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。
        mLocationOption.setInterval(5000);
        //设置是否返回地址信息(默认返回地址信息)
        mLocationOption.setNeedAddress(true);
        //设置是否允许模拟位置,默认为true,允许模拟位置
        mLocationOption.setMockEnable(true);
        //单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。
        mLocationOption.setHttpTimeOut(20000);
        //关闭缓存机制
        mLocationOption.setLocationCacheEnable(false);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }

    public void stopLocation() {
        if (null != mLocationClient) {
            mLocationClient.stopLocation();//停止定位后,本地定位服务并不会被销毁
        }
    }

    public void destoryLocation() {
        if (null != mLocationClient) {
            mLocationClient.unRegisterLocationListener(mLocationListener);
            mLocationClient.onDestroy();//销毁定位客户端,同时销毁本地定位服务。
            mLocationClient = null;
        }
    }

}

把定位信息上传到服务器的类
上传服务我写了一个UploadLocation方法,开启当前服务,该服务一旦开启,会自动调用onHandleIntent()方法。在onHandleIntent()方法中,我会把从网上得到的坐标信息通过一个流发送到服务器

package com.dongnao.battery.location;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.util.Log;

import com.dongnao.battery.Utils;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
 *定位以后把定位信息上传到服务器
 */
public class UploadService extends IntentService {


    public UploadService() {
        super("upload Location");
    }
//开启当前服务
    public static void UploadLocation(Context context, String location) {
        Intent intent = new Intent(context, UploadService.class);
        intent.putExtra("DATA", location);
        context.startService(intent);
    }
//1,IntentService 开启后会自动调用该方法
//2,从网络上得到的坐标信息(location)通过一个流发送
//到一个url服务器上(https://www.baidu.com/备注:这个路径是我胡乱写的)
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String location = intent.getStringExtra("DATA");
        Log.i("dongnao", "IntentService 获得了位置信息:" + location);
        HttpURLConnection conn = null;
        OutputStream os = null;
        try {
            conn = (HttpURLConnection) new URL("https://www.baidu.com/")
                    .openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            os = conn.getOutputStream();
            os.write(location.getBytes());
            os.flush();
            Log.i("dongnao", "IntentService 上传位置信息");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            Utils.safeColose(os);
            if (null != conn) {
                conn.disconnect();
            }
        }
    }
}

这个类是干货,这个类是定位服务,有三种方式,一个是WakeLock(本例中被注释的代码用的就是WakeLock),定义WakeLock保证后台代码长时间运行,这个时候就可以长时间的收到信息,但这种方式比较耗电,所以我们还有第二种方式和第三种方式。第二种方式就是闹钟的方式,使用闹钟就不会长期占用CPU

package com.dongnao.battery.location;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.job.JobScheduler;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.dongnao.battery.JobManager;



public class LocationService extends Service {
    //使用WakeLock保证后台代码长时间的一直执行,但比较耗电,现在被android弃用
    private PowerManager.WakeLock locationLock;
	//使用闹钟需要一个intent
    private Intent alarmIntent;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        
        //使用WeakLock,拿到电源管理服务
//        PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        //判断是否支持
//        pm.isWakeLockLevelSupported(PowerManager.PARTIAL_WAKE_LOCK);
        //只唤醒cpu
//        locationLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
//                "location_lock");
//        locationLock.acquire();


        //创建一个闹钟
        alarmKeep();
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        //释放
        LocationManager.getInstance().destoryLocation();
        //不用的时候注销广播接收者
        unregisterReceiver(alarmReceiver);
//        if (null != locationLock) {
//            locationLock.release();
//        }
    }
//1,用来解决即时性很高的需求,比如每隔五秒钟来做一次事情,我们可以使用闹钟,
//闹钟可以间歇性的使用CPU,比如本应用就是每隔5秒钟使用一次cpu,这样就不会在后台一直运行,
//但是如果我们使用WeakLock,即使屏幕关掉了,cpu也会继续工作,这样就会比较耗电
    private void alarmKeep() {
        alarmIntent = new Intent();
		//Location是自己随便定义的
        alarmIntent.setAction("LOCATION");
        //创建延迟意图,心跳也可以使用闹钟
        PendingIntent broadcast = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
        //获得闹钟管理器
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        //动态注册广播接受者,来进行闹钟的操作
        IntentFilter filter = new IntentFilter();
		//Location是自己随便定义的
        filter.addAction("LOCATION");
        registerReceiver(alarmReceiver,filter);
        //每隔 5s 发送一个广播
        alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime(),
                5_000,broadcast);
    }

    BroadcastReceiver alarmReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
			//如果intent.getAction()是LOCATION
            if (TextUtils.equals(intent.getAction(),"LOCATION")){
                LocationManager.getInstance().startLocation(LocationService.this);
            }
        }
    };
}

locationService,为定位的类,定位以后通过UploadService上传定位信息
文件清单中注册两个类,单独开启一个进程

         <service
            android:name=".location.LocationService"
            android:process=":location" />

        <service
            android:name=".location.UploadService"
            android:process=":location" />

第三jobScheduler
推送就可以使用jobScheduler,使用jobScheduler可以定时的发送一些东西
MyJobService类

package com.dongnao.battery;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.os.AsyncTask;
import android.os.PersistableBundle;
import android.util.Log;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 1,将来所有的事情,比如上传信息,就通过这个服务来完成,不在使用UploadService了。
 * 2,要在功能清单中注册,但开一个进程
 *   <service
 * android:name=".MyJobService"
 * android:permission="android.permission.BIND_JOB_SERVICE"
 * android:process=":location" />
 */
public class MyJobService extends JobService {

    public static final String TAG = "MyJobService";

    /**
     *
     * @param params 1,我们通过JobScheduler执行任我的时候,任务中的信息可以通过该参数得到
     *               2,工作在执行的时候,它身上各种信息都在params里
     * @return
     */
    @Override
    public boolean onStartJob(JobParameters params) {

        //当任务执行完毕时你需要调用jobFinished(JobParameters params, boolean needsRescheduled)来通知系统
        new MyAsyncTask().execute(params);//提交到系统中这些服务的参数先拿到
        //1,如果返回值是false,这个方法返回时任务已经执行完毕。就不会去执行onStopJob方法
        //2,如果返回值是true,那么这个任务正要被执行,我们就需要开始执行任务。
        //要手动调用jobFinished()来通知系统。
        return true;
    }

    //当系统接收到一个取消请求时
    @Override
    public boolean onStopJob(JobParameters params) {
        //如果onStartJob返回false,那么onStopJob不会被调用
        //如果onStopJob()返回 true 则会重新计划这个job,很少会返回true,一般都是返回false
        return false;
    }


    /**
     * 最好单独写一个文件,这里我就写到一起了
     * Params:启动任务时输入的参数类型.
     * <p>
     * Progress:后台任务执行中返回进度值的类型.
     * <p>
     * Result:后台任务执行完成后返回结果的类型.
     */
    class MyAsyncTask extends AsyncTask<JobParameters, Void, Void> {
        JobParameters jobParameters;

        @Override
        protected Void doInBackground(JobParameters[] objects) {
            jobParameters = objects[0];
            Log.i(TAG, jobParameters.getJobId() + " 任务开始执行......");
            //拿到包裹
            PersistableBundle extras = jobParameters.getExtras();
            //获取包裹中的定位信息
            String location = extras.getString("DATA");
            Log.i(TAG, jobParameters.getJobId() + " 上传:" + location);
            HttpURLConnection conn = null;
            OutputStream os = null;
            try {
                //服务器路径随便填写
                conn = (HttpURLConnection) new URL("https://www.baidu.com/")
                        .openConnection();
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
                os = conn.getOutputStream();
                os.write(location.getBytes());
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                Utils.safeColose(os);
                if (null != conn) {
                    conn.disconnect();
                }
            }
            return null;
        }

        /**
         * doInBackground:必须重写,异步执行后台线程要完成的任务,耗时操作将在此方法中完成.
         * <p>
         * onPreExecute:执行后台耗时操作前被调用,通常用于进行初始化操作.
         * <p>
         * onPostExecute:当doInBackground方法完成后,系统将自动调用此方法,并将doInBackground方法返回的值传入此方法.通过此方法进行UI的更新.
         * <p>
         * onProgressUpdate:当在doInBackground方法中调用publishProgress方法更新任务执行进度后,将调用此方法.通过此方法我们可以知晓任务的完成进度.
         */
        @Override
        protected void onPostExecute(Void s) {
            //1,因为onStartJob返回的是true,所以当任务执行完毕之后,需要调用
            // jobFinished来让系统知道这个任务已经结束,如果是false,就不需要执行这个代码
            //2,系统可以将下一个任务添加到队列中
            //3,参数true表示需要重复执行,false反之,很少写true,绝大部分情况下都是false
            jobFinished(jobParameters, false);
            Log.i(TAG, jobParameters.getJobId() + "任务执行完成......");
        }
    }
}

JobManager类

package com.dongnao.battery;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;
import android.os.PersistableBundle;

import java.util.List;

//各种服务性操作,google建议用它替换掉普通的服务
public class JobManager {

    static JobManager instance;
    //把一些不是特别紧急(实时)的任务放到更合适的时机批量处理
    // 好处1、避免频繁的唤醒硬件模块,比如网络模块等
    // 好处2、避免在不合适的时候执行一些耗电的任务,比如我们第二部分这个代码
	//  alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime(),
    //           5_000,broadcast);
	//每隔5秒就接收到坐标,就会把这个坐标发送到服务器,假设现在我要统计一个人一天的行程,这样的发送
	//显然没有必要。 像这样的需求我们可以一次整合很多内容在一次性的发送。把很多工作流合并在一起,起到
	//一个合并的作用。
    private JobScheduler jobScheduler;
    private Context context;

    private static final int jobId=0;
    //单例模式,省去了非空判断,自己加上
    public static JobManager getInstance() {
        if (null == instance)
            instance = new JobManager();
        return instance;
    }
     //初始化工作流
     //在Application的onCreate()中初始化
    public void init(Context context) {
        this.context = context.getApplicationContext();
		//jobScheduler本身就是一个系统服务
		//所有系统服务的初始化都有两种,一种是通过aidl进程间通讯,另外一种就是反射
        jobScheduler = (JobScheduler)
                context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

    }

    /**
     * 添加一个任务,把服务器传回来的信息一个个添加进来
	 * 比如每五秒收到一次坐标,我要把这些坐标任务全部添加在一起,再统一去延迟执行
     * @param location
     */
     //把服务器传回来的信息一个个添加进来
    public void addJob(String location) {
        if (null == jobScheduler) {
            return;
        }
        //1,jobinfo中会用来存放工作流相关的信息
        //2, 当我们添加任我的时候需要JobInfo
        JobInfo pendingJob = null;
        //整合多个job,Build.VERSION_CODES.N(android 7.0)以上和以下分两种情况处理。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //1,查找id是0(即jobId)的job,id号是由用户决定的。
           //2, 等下我们在添加的时候,会先到已经有的一个工作队列(比如
            //我们有10个工作,jobScheduler会拿一个集合存放,这个集合就是工作队列),在我们添加id为0的任务之前,
            //有可能已经有很多任务在这个工作队列里面了。
            //3,工作队列第一次肯定是空的,非第一次就未必,这句代码是查找先前的工作队列中有没有内容
            pendingJob = jobScheduler.getPendingJob(jobId);
        } else {
            List<JobInfo> allPendingJobs = jobScheduler.getAllPendingJobs();
            for (JobInfo info : allPendingJobs) {
            //查找IDhao相同的工作/任务
                if (info.getId() == jobId) {
                    pendingJob = info;
                    break;
                }
            }
        }
        //找到待执行的job
        if (null != pendingJob) {
            //1,多个坐标信息拼到一起上传
            //2,android 5.0以后才可以使用JobScheduler
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //1,与Intent一样,用来存数据
                //1,PersistableBundle就是存东西的对象,与我们平时用的bundle没啥区别
                PersistableBundle extras = pendingJob.getExtras();
                //获得上一次设置的location数据
                String data = extras.getString("DATA");
                //1,如果有多条就自定义,这个连接符要和服务器商量,比如 多条坐标数据用@隔开
                //2,每5秒就会拼接一次,只要有任务就拼接字符串
                location = data + "@" + location;
                //这次任务完成了
                jobScheduler.cancel(jobId);
            }
        }
        //1, jobid :0
        //2,创建任务
        PersistableBundle extras = new PersistableBundle();
        extras.putString("DATA",location);
        //1,每来一个job,创建一个job
        //2,添加任务的时候需要一个叫JobInfo的内容,有了这个内容后可以把地图坐标信息,
        //3,把地图信息放到extras里,就可以生成JobInfo
        JobInfo jobInfo = new
        // 把某个工作加进来,jobID是加进来工作的ID
                JobInfo.Builder(jobId,
                //1,把jobservice绑定到jobInfo上面,执行的时候服务就会被跑起来,MyJobService就是需要执行的服务
                //2,MyJobService会调用很多次,调用一次就会拼接一次Location,这样的话就会有大量的工作排好队
                //这些工作什么时候执行呢?充电和链接wifi的时候就开始执行任务,就开始上传。调用
                //jobScheduler.schedule(jobInfo);后,刚刚排队的任务就会一个一个跑,每个任务跑都会拼成
                //location@的样子。服务往服务器提交(在MyJobService的onStartJob()里写)之前,这些东西
                //会链接在一起。
                //3,把拼接的东西加入工作队列
                new ComponentName(context, MyJobService.class))
                //是么时候执行jobservice,只在充电的时候执行
                .setRequiresCharging(true)
                //不是蜂窝网络,就是使用wifi
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                .setExtras(extras).build();

        //1,提交任务
        //2,id为0的服务会全部累计在一个队列里面,提交任务完成后,
        // 满足充电无线网这两个条件的时候,所有id号为0的这一组服务,就会按照特定的优先级,
        //  一个一个的去执行。
        jobScheduler.schedule(jobInfo);
    }

}

在LocationManager中调用

package com.dongnao.battery.location;

import android.content.Context;
import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.dongnao.battery.JobManager;


public class LocationManager {
    //声明AMapLocationClient类对象
    private AMapLocationClient mLocationClient;

    private static LocationManager instance;

    private Context applicationContext;

    public LocationManager() {

    }

    public static LocationManager getInstance() {
        if (null == instance) {
            instance = new LocationManager();
        }
        return instance;
    }

    //声明定位回调监听器
    public AMapLocationListener mLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation aMapLocation) {
            if (aMapLocation != null) {
                if (aMapLocation.getErrorCode() == 0) {
                    //获得json
                    String location = aMapLocation.toStr();
                    //启动IntentService 上传坐标数据
                    // 主要不是实时需要的,延迟执行
//                    UploadService.UploadLocation(applicationContext, location);
                    //每隔5秒会执行一次
                    JobManager.getInstance().addJob(location);
                } else {
                    //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
                    Log.e("AmapError", "location Error, ErrCode:"
                            + aMapLocation.getErrorCode() + ", errInfo:"
                            + aMapLocation.getErrorInfo());
                }
            }
        }
    };

    public void startLocation(Context context) {
        if (null != mLocationClient) {
            mLocationClient.startLocation();
            return;
        }
        applicationContext = context.getApplicationContext();
        //初始化定位
        mLocationClient = new AMapLocationClient(applicationContext);
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener);
        //声明AMapLocationClientOption对象
        AMapLocationClientOption mLocationOption = null;
        //初始化AMapLocationClientOption对象
        mLocationOption = new AMapLocationClientOption();
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。
        mLocationOption.setInterval(5000);
        //设置是否返回地址信息(默认返回地址信息)
        mLocationOption.setNeedAddress(true);
        //设置是否允许模拟位置,默认为true,允许模拟位置
        mLocationOption.setMockEnable(true);
        //单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。
        mLocationOption.setHttpTimeOut(20000);
        //关闭缓存机制
        mLocationOption.setLocationCacheEnable(false);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }

    public void stopLocation() {
        if (null != mLocationClient) {
            mLocationClient.stopLocation();//停止定位后,本地定位服务并不会被销毁
        }
    }

    public void destoryLocation() {
        if (null != mLocationClient) {
            mLocationClient.unRegisterLocationListener(mLocationListener);
            mLocationClient.onDestroy();//销毁定位客户端,同时销毁本地定位服务。
            mLocationClient = null;
        }
    }

}

在这里调用

//每隔五秒添加一个服务,但这个服务并不是5秒就执行,会把这些服务全部累计在一个队列里面
 JobManager.getInstance().addJob(location);

在Application的onCreate()中初始化

 JobManager.getInstance().init(this);

我们测试发现wakelock变成小黄点了,不再是一条直线

发布了214 篇原创文章 · 获赞 17 · 访问量 8万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览