1.创建鹰眼服务


创建服务
获取到服务ID158542

2.下载demo


1)Androidmanifest.xml权限,ak

<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.READ_LOGS"/>
    <uses-permission android:name="android.permission.VIBRATE"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

<application >
    <meta-data
                android:name="com.baidu.lbsapi.API_KEY"
                android:value="tGb2SGaEsKcG2MzxQ9jTzRxl2ZGgGTGb"/>
   <service
                android:name="com.baidu.trace.LBSTraceService"
                android:enabled="true"
                android:exported="true"
                android:process=":remote"
        />
</application>

2)加入库jar和so
把so库libBaiduMapSDK_base_v4_2_1.so,libBaiduMapSDK_map_v4_2_1.so
libBaiduTraceSDK_v3_0_7.so放入libs/armeabi目录下
jar包BaiduLBS_Android.jar,BaiduTraceSDK_V3_0_7.jar
bos-android-sdk-1.0.3.jar,okhttp-3.8.1.jar,okio-1.13.0.jar放入libs目录下
在build.gradle里添加

sourceSets {
        main {
            jniLibs.srcDir 'libs'
        }
    }

3)TrackApplication.java
添加service_id
com.baidu.track目录下的TrackApplication.java

/**
     * 轨迹服务ID
     */
    public long serviceId = 158542;

    // 初始化轨迹服务客户端
    LBSTraceClient mClient = new LBSTraceClient(mContext);
       // 初始化轨迹服务
       Trace mTrace mTrace = new Trace(serviceId, entityName);

4)TracingActivity.java轨迹追踪
com.baidu.track.activity
//开启鹰眼服务,启动鹰眼 service
trackApp.mClient.startTrace(trackApp.mTrace, traceListener);
开启轨迹采集,启动轨迹追踪。至此,正式开启轨迹追踪
trackApp.mClient.startGather(traceListener)
5)结束轨迹追踪
停止轨迹服务:此方法将同时停止轨迹服务和轨迹采集,完全结束鹰眼轨迹服务。
若需再次启动轨迹追踪,需重新启动服务和轨迹采集
trackApp.mClient.stopTrace(trackApp.mTrace, traceListener);
停止轨迹采集:此方法将停止轨迹采集,但不停止轨迹服务(即,不再采集轨迹点了,但鹰眼 service 还存活)。
若需再次启动轨迹追踪,直接调用mTraceClient.startGather()方法开启轨迹采集即可,无需再次启动轨迹服务。此方式可应用于频繁中断轨迹追踪的场景,可避免频繁启动服务
trackApp.mClient.stopGather(traceListener);

3.服务保活

Android系统对应用长时间运行的要求日趋严格,轨迹追踪应用可能会被系统杀死,导致轨迹上传不完整

4.Android 鹰眼 后台启动轨迹追踪采集

直接通过Service后台运行采集gps数据

public class TrackService extends Service {
    /**
     * 轨迹客户端
     */
    public LBSTraceClient mClient = null;
    /**
     * 轨迹服务
     */
    public Trace mTrace = null;

    /**
     * 轨迹服务ID
     */
    public long serviceId = 158542;
    /**
     * Entity标识
     */
    public String entityName = "LYY";
    //定位周期单位秒
    int gatherInterval = 5;
    //打包回传周期,单位秒
    int packInterval = 10;
    /**
     * 轨迹服务监听器
     */
    private OnTraceListener traceListener = null;
    private LocRequest locRequest = null;

    private PowerManager.WakeLock wakeLock = null;
    private TrackReceiver trackReceiver = null;
    private PowerManager powerManager = null;

    static class RealTimeHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }


    public TrackService() {
    }

    @Override
    public IBinder onBind(Intent intent) {

        throw new UnsupportedOperationException("Not yet implemented");
    }




    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("bshui","service---onCreate-------");

        //1.初始化轨迹服务
        // 初始化轨迹服务客户端
        mClient = new LBSTraceClient(getApplicationContext());
        // 初始化轨迹服务
        mTrace  = new Trace(serviceId, entityName);
        //2.设置定位和回传周期
        //自定义定位频率和打包回传频率,频率可设置范围为:2~300秒。
        // 例如:定位频率为5s,打包回传频率为10s,则2次定位后打包回传一次
        mClient.setInterval(gatherInterval,packInterval);

        //3)开启轨迹追踪
        //开启鹰眼服务,启动鹰眼 service
        mClient.startTrace(mTrace,traceListener);
        //开启轨迹采集,启动轨迹追踪。至此,正式开启轨迹追踪
        mClient.startGather(traceListener);


        powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);

        traceListener = new OnTraceListener(){
            /**
             * 绑定服务回调接口
             * @param i 状态码
             * @param s 消息0,成功,1失败
             */
            @Override
            public void onBindServiceCallback(int i, String s) {
                Log.i("bshui","onBindServiceCallback errorNo:"+i+
                " message"+s);
            }

            /**
             * 开启服务回调接口
             * @param i 状态码
             * @param s 消息
             *                <pre>10000:请求发送失败</pre>
             *                <pre>10001:服务开启失败</pre>
             *                <pre>10002:参数错误</pre>
             *                <pre>10003:网络连接失败</pre>
             *                <pre>10004:网络未开启</pre>
             *                <pre>10005:服务正在开启</pre>
             *                <pre>10006:服务已开启</pre>
             */
            @Override
            public void onStartTraceCallback(int i, String s) {
                    if(i==0 || i>=10003){
                        //注册广播(电源锁,GPS状态)
                        if (null == wakeLock) {
                            wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "track upload");
                        }
                        if (null == trackReceiver) {
                            trackReceiver = new TrackReceiver(wakeLock);
                        }

                        IntentFilter filter = new IntentFilter();
                        filter.addAction(Intent.ACTION_SCREEN_OFF);
                        filter.addAction(Intent.ACTION_SCREEN_ON);
                        filter.addAction(Intent.ACTION_USER_PRESENT);
                        filter.addAction(StatusCodes.GPS_STATUS_ACTION);
                        getApplication().registerReceiver(trackReceiver, filter);

       }

                Log.i("bshui","onStartTraceCallback errorNo:"+i+
                        " message"+s);
            }
            /**
             * 停止服务回调接口
             * @param i 状态码
             * @param s 消息
             *                <p>
             *                <pre>0:成功</pre>
             *                <pre>11000:请求发送失败</pre>
             *                <pre>11001:服务停止失败</pre>
             *                <pre>11002:服务未开启</pre>
             *                <pre>11003:服务正在停止</pre>
             */
            @Override
            public void onStopTraceCallback(int i, String s) {
                if(i==0 || i==11004){
                    getApplication().unregisterReceiver(trackReceiver);
                }
                Log.i("bshui","onStopTraceCallback errorNo:"+i+
                        " message"+s);

            }

            @Override
            public void onStartGatherCallback(int i, String s) {
                Log.i("bshui","onStartGatherCallback errorNo:"+i+
                        " message"+s);
            }

            @Override
            public void onStopGatherCallback(int i, String s) {
                Log.i("bshui","onStopGatherCallback errorNo:"+i+
                        " message"+s);
            }

            @Override
            public void onInitBOSCallback(int i, String s) {
                Log.i("bshui","onInitBOSCallback:errorNo:"+i+
                " message:"+s);
            }

            @Override
            public void onPushCallback(byte b, PushMessage pushMessage) {

            }
        };


        // 在Android 6.0及以上系统,若定制手机使用到doze模式,请求将应用添加到白名单。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String packageName = getApplicationContext().getPackageName();
            boolean isIgnoring = powerManager.isIgnoringBatteryOptimizations(packageName);
            if (!isIgnoring) {
                Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + packageName));
                try {
                    startActivity(intent);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        //开启鹰眼服务,启动鹰眼 service
        mClient.startTrace(mTrace,traceListener);
        //开启轨迹采集,启动轨迹追踪。至此,正式开启轨迹追踪
        mClient.startGather(traceListener);

    }
}

5.轨迹查询和实时监控

public class MainActivity extends AppCompatActivity {
    private MapView mapView = null;
    private BaiduMap mBaiduMap = null;
    private MapStatus mapStatus = null;
    private Marker mMoveMarker = null;
    private Button btSearch;
    private Button btTrack;
    private boolean isTrack=true;

    /**
     * 路线覆盖物
     */
    public Overlay polylineOverlay = null;
    private AtomicInteger mSequenceGenerator = new AtomicInteger();
    /**
     * 轨迹点集合
     */
    private List<LatLng> trackPoints = new ArrayList<>();
    /**
     * 历史轨迹请求
     */
    private HistoryTrackRequest historyTrackRequest = new HistoryTrackRequest();
    /**
     * 轨迹客户端
     */
    public LBSTraceClient mClient = null;
    /**
     * 轨迹服务
     */
    public Trace mTrace = null;

    /**
     * 轨迹服务ID
     */
    public long serviceId = 158542;
    /**
     * Entity标识
     */
    public String entityName = "LYY"; //LYY
    /**
     * 轨迹监听器(用于接收历史轨迹回调)
     */
    private OnTrackListener mTrackListener = null;
    //定位周期单位秒
    int gatherInterval = 5;
    //打包回传周期,单位秒
    int packInterval = 10;
    //开始时间(Unix时间戳)
    int startTime = (int) (System.currentTimeMillis() / 1000 - 12 * 60 * 60);
    //结束时间(Unix时间戳)
    int endTime = (int) (System.currentTimeMillis() / 1000);
    //分页大小
    int pageSize = 1000;
    //分页索引
    int pageIndex = 1;

    private LocRequest locRequest = null;
    static class RealTimeHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }
    /**
     * 实时定位任务
     */
    private RealTimeHandler realTimeHandler = new RealTimeHandler();

    private RealTimeLocRunnable realTimeLocRunnable = null;

    //Entity 监听器
    OnEntityListener entityListener = new OnEntityListener() {
        @Override
        public void onReceiveLocation(TraceLocation traceLocation) {
            super.onReceiveLocation(traceLocation);

            if(isTrack) {
                double latitude = traceLocation.getLatitude();
                double longitude = traceLocation.getLongitude();

                LatLng currentLatLng = new LatLng(latitude, longitude);
                setMapStatus(currentLatLng, 17.0f);

                addMarker(currentLatLng);
            }

        }
    };

    class RealTimeLocRunnable implements Runnable {

        private int interval = 0;

        public RealTimeLocRunnable(int interval) {
            this.interval = interval;
        }

        @Override
        public void run() {

            mClient.queryRealTimeLoc(locRequest, entityListener);
            realTimeHandler.postDelayed(this, interval * 1000);

        }
    }

    /**
     * 实时定位任务
     */
    public void startRealTimeLoc(int interval){

        realTimeLocRunnable = new RealTimeLocRunnable(interval);
        realTimeHandler.post(realTimeLocRunnable);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);

        btSearch = (Button)findViewById(R.id.btSearch);
        btTrack  = (Button)findViewById(R.id.btTrack);

        mapView = (MapView)findViewById(R.id.track_query_mapView);
        mBaiduMap = mapView.getMap();
        mBaiduMap.setMyLocationEnabled(true);
        //1.初始化轨迹服务
        // 初始化轨迹服务客户端
        mClient = new LBSTraceClient(getApplicationContext());
        // 初始化轨迹服务
        mTrace  = new Trace(serviceId, entityName);
         locRequest = new LocRequest(serviceId);
         //查询实时定位位置
         startRealTimeLoc(packInterval);

        //隐藏左下角的logo
        View child = mapView.getChildAt(1);
        if(child !=null){
            child.setVisibility(View.INVISIBLE);
        }

        //查询轨迹,时间设置为最近12小时
        btSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                isTrack = false;
                queryHistoryTrack();
            }
        });

        btTrack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBaiduMap.clear();
                mMoveMarker=null;

                isTrack = true;
            }
        });

        mTrackListener = new OnTrackListener(){

            @Override
            public void onHistoryTrackCallback(HistoryTrackResponse response) {
               int total = response.getTotal();

                if(total == 0){
                    Toast.makeText(getApplicationContext(),
                            "没有查到轨迹",
                            Toast.LENGTH_LONG).show();
                }else{
                    List<TrackPoint> points = response.getTrackPoints();
                    if(null != points){

                        for(TrackPoint trackPoint : points){
                            double latitude = trackPoint.getLocation().getLatitude();
                            //采集点集合
                            trackPoints.add(convertTrace2Map(trackPoint.getLocation()));

                        }
                    }

                    if(total > pageSize*pageIndex ){
                        historyTrackRequest.setPageIndex(++pageIndex);
                        queryHistoryTrack();

                    }else{
                        //SortType:轨迹排序规则
                        drawHistoryTrack(trackPoints,SortType.asc);

                    }
                }
            }
        };


    }

    /**
     * 将轨迹坐标对象转换为地图坐标对象
     *
     * @param traceLatLng
     *
     * @return
     */
    public static LatLng convertTrace2Map(com.baidu.trace.model.LatLng traceLatLng) {
        return new LatLng(traceLatLng.latitude, traceLatLng.longitude);
    }

    /**
     * 获取请求标识
     *
     * @return
     */
    public int getTag() {
        return mSequenceGenerator.incrementAndGet();
    }
    /**
     * 初始化请求公共参数
     *
     * @param request
     */
    public void initRequest(BaseRequest request) {
        request.setTag(getTag());
        request.setServiceId(serviceId);
    }

    /**
     * 查询历史轨迹
     */
    private void queryHistoryTrack() {

        initRequest(historyTrackRequest);

        historyTrackRequest.setEntityName(entityName);
        historyTrackRequest.setStartTime(startTime);
        historyTrackRequest.setEndTime(endTime);
        historyTrackRequest.setPageIndex(pageIndex);
        historyTrackRequest.setPageSize(pageSize);
        // 设置需要纠偏
        historyTrackRequest.setProcessed(true);
        // 创建纠偏选项实例
        ProcessOption processOption = new ProcessOption();
        // 设置需要去噪
        processOption.setNeedDenoise(true);
        // 设置需要抽稀
        processOption.setNeedVacuate(true);
        // 设置需要绑路
        processOption.setNeedMapMatch(true);
        // 设置精度过滤值(定位精度大于100米的过滤掉)
        processOption.setRadiusThreshold(100);
        // 设置交通方式为驾车
        processOption.setTransportMode(TransportMode.driving);
        // 设置纠偏选项
        historyTrackRequest.setProcessOption(processOption);
        // 设置里程填充方式为驾车
        historyTrackRequest.setSupplementMode(SupplementMode.driving);

        mClient.queryHistoryTrack(historyTrackRequest, mTrackListener);
    }

    public void setMapStatus(LatLng point, float zoom) {
        MapStatus.Builder builder = new MapStatus.Builder();
        mapStatus = builder.target(point).zoom(zoom).build();
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
    }



    /**
     * 添加地图覆盖物
     */
    public void addMarker(LatLng currentPoint) {
        if (null == mMoveMarker) {

            OverlayOptions overlayOptions = new MarkerOptions()
                    .position(currentPoint)
                    .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_point))
                    .draggable(true);
            mMoveMarker = (Marker) mBaiduMap.addOverlay(overlayOptions);

            return;
        }


        mMoveMarker.setPosition(currentPoint);

    }

    public void animateMapStatus(List<LatLng> points) {
        if (null == points || points.isEmpty()) {
            return;
        }
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (LatLng point : points) {
            builder.include(point);
        }
        MapStatusUpdate msUpdate = MapStatusUpdateFactory.newLatLngBounds(builder.build());
        mBaiduMap.animateMapStatus(msUpdate);
    }

    public void animateMapStatus(LatLng point, float zoom) {
        MapStatus.Builder builder = new MapStatus.Builder();
        mapStatus = builder.target(point).zoom(zoom).build();
        mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
    }
    /**
     * 绘制历史轨迹
     */
    public void drawHistoryTrack(List<LatLng> points, SortType sortType) {
        // 绘制新覆盖物前,清空之前的覆盖物
        mBaiduMap.clear();
        if (points == null || points.size() == 0) {
            if (null != polylineOverlay) {
                polylineOverlay.remove();
                polylineOverlay = null;
            }
            return;
        }

        if (points.size() == 1) {
            OverlayOptions startOptions = new MarkerOptions()
                    .position(points.get(0))
                    .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_start))
                    .zIndex(9).draggable(true);
            mBaiduMap.addOverlay(startOptions);
            animateMapStatus(points.get(0), 16.0f);
            return;
        }

        LatLng startPoint;
        LatLng endPoint;
        if (sortType == SortType.asc) {
            startPoint = points.get(0);
            endPoint = points.get(points.size() - 1);
        } else {
            startPoint = points.get(points.size() - 1);
            endPoint = points.get(0);
        }

        // 添加起点图标
        OverlayOptions startOptions = new MarkerOptions()
                .position(startPoint)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_start))
                .zIndex(9).draggable(true);
        // 添加终点图标
        OverlayOptions endOptions = new MarkerOptions().position(endPoint)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_end))
                .zIndex(9).draggable(true);

        // 添加路线(轨迹)
        OverlayOptions polylineOptions = new PolylineOptions().width(10)
                .color(Color.BLUE).points(points);

        mBaiduMap.addOverlay(startOptions);
        mBaiduMap.addOverlay(endOptions);
        polylineOverlay = mBaiduMap.addOverlay(polylineOptions);

        OverlayOptions markerOptions =
                new MarkerOptions()
                        .flat(true)
                        .anchor(0.5f, 0.5f)
                        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_point))
                        .position(points.get(points.size() - 1));
                       // .rotate((float) CommonUtil.getAngle(points.get(0), points.get(1)));
        mMoveMarker = (Marker) mBaiduMap.addOverlay(markerOptions);

        animateMapStatus(points);
    }
}

6.Demo