之前我也写过一些博客,但我表达能力不是很强,所以没有坚持下去!!我目前在学习反汇编和手机安全这方面的知识,等我懂了,我会写一下反汇编和手机安全方面的知识来和大家分享,共同学习!!
好了,废话我也不多说了!!来撸代码
就上一个礼拜,老大叫我做一个运动轨迹,啥?运动轨迹,好吧,懵逼了,查资料,好吧发现百度开发平台有个叫百度鹰眼的可以做这个
http://lbsyun.baidu.com/index.php?title=android-yingyan,不知道自己看看,不过这个官方文档写的真的是不太完善,我看了两天才慢慢的理清楚里面的关系,可以是我能力不够的关系。
好了,关系理清楚了,接下来就是撸代码,这里面的这个latlng坐标类是关键,用它可里面经纬你就可以清楚的画出你的运动轨迹,开发之前的配置我就不说,都能百度到,我来说说开发要注意的细节,这个ak是必须的,怎么申请,请百度,这是基础,申请到之后就可以开发了,没完成申请就不要往下看了,还有就是jar包的引用
http://lbsyun.baidu.com/index.php?title=android-yingyan/sdkandev-download这是官方的下载,因为这方面的东西更新很快。。。。,这个轨迹服务ID是关键,不然你都不知道它为什么没有运行起来。。http://lbsyun.baidu.com/index.php?title=yingyan/manage
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
当你准备好了基础配置,接下来就是进入主题了,百度鹰眼有个强大的后台,所以你只要理解,他每个提供的每个接口,你就会开发。。
首先你要自定义一个entity标识,因为他后台是根据你转上去这个标识来反馈你所需要的信息内容,我写了一个登入界面来设置用户注册的不同的标识,
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.baidu.track.R;
import com.baidu.track.utils.CommonUtil;
import com.baidu.track.utils.Constants;
import com.baidu.track.utils.CrashHandler;
import com.baidu.track.view.LoginView;
public class LoginActivity extends BaseActivity implements OnClickListener, LoginView {
private EditText telephoneText = null;
private Button loginBtn = null;
private String telephoneNO = "";
private TrackApplication trackApp = null;
private long exitTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
trackApp = (TrackApplication) getApplicationContext();
telephoneText = (EditText) findViewById(R.id.telephone);
loginBtn = (Button) findViewById(R.id.login);
StringBuilder strBuilder = new StringBuilder("<font face='" + getString(R.string.font_type) + "'>");
strBuilder.append(getString(R.string.login_title)).append("</font>");
TextView loginText = (TextView) findViewById(R.id.login_text);
//从提供的HTML字符串返回可显示的样式文本
loginText.setText(Html.fromHtml(strBuilder.toString()));
// 处理未捕获异常
CrashHandler handler = CrashHandler.getInstance();
handler.init(trackApp);
}
@Override
protected void onStart() {
super.onStart();
loginBtn.setOnClickListener(this);
//焦点事件
telephoneText.addTextChangedListener(new TextWatcher() {
int beforeTextLength = 0;//文本开始的长度
int onTextLength = 0;//输入后的文本长度
boolean isChanged = false;
int location = 0;// 记录光标的位置
private char[] tempChar;
private StringBuffer buffer = new StringBuffer();
int blankSpaceIndex1 = 0;
//调用此方法以通知您,在s内,从开始开始的计数字符将被具有长度的新文本替换。
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
Log.d("xxxx",arg0.toString()+arg1+""+arg2 +""+arg3+"");
// TODO Auto-generated method stub
beforeTextLength = arg0.length();
if (buffer.length() > 0) {
buffer.delete(0, buffer.length());
}
blankSpaceIndex1 = 0;
for (int i = 0; i < arg0.length(); i++) {
if (arg0.charAt(i) == ' ') {
blankSpaceIndex1++;
}
}
}
//调用此方法以通知您,在s内,从开始处开始的计数字符刚刚替换了之前具有长度的旧文本。
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// Log.d("xxxx",arg0+""+arg1+""+arg2 +""+arg3+"");
// TODO Auto-generated method stub
onTextLength = arg0.length();
buffer.append(arg0.toString());
//输入的长度不匹配
if (onTextLength == beforeTextLength || onTextLength <= 3
|| isChanged) {
isChanged = false;
return;
}
isChanged = true;
}
//调用此方法以通知您,在s内的某处,文本已更改。
@Override
public void afterTextChanged(Editable telephone) {
// Log.d("xxxx",telephone.toString());
// TODO Auto-generated method stub
if (isChanged) {
location = telephoneText.getSelectionEnd();
int index = 0;
while (index < buffer.length()) {
if (buffer.charAt(index) == ' ') {
buffer.deleteCharAt(index);
} else {
index++;
}
}
index = 0;
int blankSpaceIndex2 = 0;
while (index < buffer.length()) {
if ((index == 3 || index == 8)) {
buffer.insert(index, ' ');
blankSpaceIndex2++;
}
index++;
}
if (blankSpaceIndex2 > blankSpaceIndex1) {
location += (blankSpaceIndex2 - blankSpaceIndex1);
}
tempChar = new char[buffer.length()];
buffer.getChars(0, buffer.length(), tempChar, 0);
String str = buffer.toString();
if (location > str.length()) {
location = str.length();
} else if (location < 0) {
location = 0;
}
telephoneText.setText(str);
Selection.setSelection(telephoneText.getText(), location);
isChanged = false;
}
// 去除格式化手机号添加的空格
telephoneNO = telephone.toString().replaceAll(" ", "");
Message message = new Message();
if (telephoneNO.length() == Constants.TEL_NO_LEN) {
message.what = Constants.ENABLE_SEND_CAPTCHA;
loginBtn.setEnabled(true);
} else {
loginBtn.setEnabled(false);
}
}
});
}
@Override
public void onClick(View view) {
// TODO Auto-generated method stub
switch (view.getId()) {
case R.id.login:
turnToTravel();
break;
}
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void turnToTravel() {
//
trackApp.setEntityName(telephoneNO);
Intent intent = new Intent(this, TravelActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
//跳转动画
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void exit() {
if ((System.currentTimeMillis() - exitTime) > 2000) {
CommonUtil.toastShow(this, getString(R.string.exit));
exitTime = System.currentTimeMillis();
} else {
finish();
System.exit(0);
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
@Override
protected int getContentViewId() {
return R.layout.activity_login;
}
}
我这里用了h5混合,因为老大说这样会省力,但我完全没觉得。。我这里用到了TextWatcher,这个是好东西,相信你看我的代码,应该能看懂,这是我做了判断,所以只能输入11位手机号,如果不喜欢,你可以改。。,下面就是我的界面
然后登入成功,之前就会进入我写好的mapView这个地图类,然后通过LBSTraceClient中的startTrace(Trace traceOnStartTraceListener onTraceListener)开启你的轨迹服务,你肯定好奇,这个方法中所以需要的参数是什么,看看这个链接http://wiki.lbsyun.baidu.com/cms/android-yingyan/doc/1216v2.1.15/index.html你就知道了,接下开启成功了,因为我现在是静止状态,就不给大家演示了,开启的要设置采集周期和打包周期,个人建议都设置5秒,那什么是采集周期,那就你如果在行走的情况下,它后台就会根据你设置的时间去上传的当前的轨迹点
我写了一个计时器来更好显示,开始,暂停,恢复,停止的不同场景
package com.baidu.track.activity;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.mapapi.utils.CoordinateConverter.CoordType;
import com.baidu.trace.TraceLocation;
import com.baidu.track.R;
import com.baidu.track.presenter.RealTimeLocPresenter;
import com.baidu.track.utils.CommonUtil;
import com.baidu.track.utils.Constants;
import com.baidu.track.utils.ViewUtil;
import com.baidu.track.view.RealTimeLocView;
import java.lang.ref.WeakReference;
import java.util.Timer;
import java.util.TimerTask;
/**
* 行程控制
*/
public class RealTimeLocFragment extends Fragment implements RealTimeLocView {
private MapView mapView = null;
private BaiduMap mBaiduMap = null;
private View view = null;
private TextView travelStateTv = null;
// 图标
private BitmapDescriptor realTimeBitmap = null;
private TrackApplication trackApp = null;
private Marker mMoveMarker = null;//地点标注
private Timer timer = null;//计时器
private RealTimeLocPresenter realTimeLocPresenter = null;
/**
* 实时定位任务
*/
private RealTimeLocTask realTimeTask = null;
/**
* 实时定位处理器
*/
private RealTimeLocHandler realTimeLocHandler = null;
private MapStatus mapStatus = null;
private LatLng lastPoint = null;
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_travel, container, false);
trackApp = (TrackApplication) getActivity().getApplicationContext();
travelStateTv = (TextView) view.findViewById(R.id.travel_state);
realTimeLocPresenter = new RealTimeLocPresenter(this, trackApp);
init();
return view;
}
private void init() {
realTimeLocHandler = new RealTimeLocHandler(this);
if (mapView != null || mBaiduMap != null) {
return;
}
mapView = (MapView) view.findViewById(R.id.loc_mapView);
mapView.showZoomControls(false);
mBaiduMap = mapView.getMap();
mBaiduMap.setViewPadding(0, 0, 0, ViewUtil.dip2px(trackApp, 77));
}
/**
* 实时定位
*/
private void queryRealTimeLoc() {
realTimeLocPresenter.queryRealTimeLoc(trackApp.getServiceId());
}
/**
* 查询实时轨迹
*/
private void queryEntityList() {
// 返回结果的类型(0 : 返回全部结果,1 : 只返回entityName的列表)
int returnType = 0;
// 活跃时间(指定该字段时,返回从该时间点之后仍有位置变动的entity的实时点集合)
int activeTime = (int) (System.currentTimeMillis() / 1000 - 5);
// 分页大小
int pageSize = 10;
// 分页索引
int pageIndex = 1;
realTimeLocPresenter.queryEntityList(trackApp.getServiceId(),
trackApp.getEntityName(), null, returnType,
activeTime, pageSize, pageIndex);
}
/**
* 实时定位任务
*
* @author baidu
*/
class RealTimeLocTask extends TimerTask {
@Override
public void run() {
// TODO Auto-generated method stub
Message message = realTimeLocHandler.obtainMessage(Constants.START_LOC);
realTimeLocHandler.sendMessage(message);
}
}
static class RealTimeLocHandler extends Handler {
private final WeakReference<RealTimeLocFragment> mRealTimeLoc;
public RealTimeLocHandler(RealTimeLocFragment mRealTimeLoc) {
this.mRealTimeLoc = new WeakReference<>(mRealTimeLoc);
}
@Override
public void handleMessage(Message msg) {
RealTimeLocFragment realTimeLoc = mRealTimeLoc.get();
switch (msg.what) {
//开始定位
case Constants.START_LOC:
if (null != realTimeLoc) {
if (realTimeLoc.trackApp.isTraceStarted()) {
realTimeLoc.queryEntityList();
} else {
realTimeLoc.queryRealTimeLoc();
}
}
break;
//实时定位
case Constants.REAL_TIME_LOC:
TraceLocation location = (TraceLocation) msg.obj;
realTimeLoc.showRealTimeTrack(location);
break;
//实时轨迹点
case Constants.ENTITY_LIST:
LatLng latLng = (LatLng) msg.obj;
realTimeLoc.drawRealTimePoint(latLng);
break;
}
}
}
public void startRealTimeLoc(int interval) {
realTimeTask = new RealTimeLocTask();
timer = new Timer();
timer.schedule(realTimeTask, 1000, interval * 1000);
realTimeLocPresenter.startRealTimeLoc();
}
public void stopRealTimeLoc() {
if (timer != null) {
timer.cancel();
timer = null;
}
if (realTimeTask!=null) {
realTimeTask.cancel();
realTimeTask = null;
}
}
/**
* 显示实时轨迹
*/
protected void showRealTimeTrack(TraceLocation location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {
return;
}
LatLng latLng = new LatLng(latitude, longitude);
if (1 == location.getCoordType()) {
LatLng sourceLatLng = latLng;
CoordinateConverter converter = new CoordinateConverter();
converter.from(CoordType.GPS);
converter.coord(sourceLatLng);
latLng = converter.convert();
}
try {
// 绘制实时点
drawRealTimePoint(latLng);
} catch (Exception e) {
}
}
/**
* 绘制实时点
*
* @param point 实时点
*/
private void drawRealTimePoint(LatLng point) {
if (null == mBaiduMap || null == point) {
return;
}
Point screenPoint = mBaiduMap.getProjection().toScreenLocation(point);
// 点在屏幕上的坐标超过限制范围,则重新聚焦底图
// 第一次定位时,聚焦底图
if (screenPoint.y < 200 || screenPoint.y > trackApp.getScreenHeight() - 500 || screenPoint.x < 200
|| screenPoint.x > trackApp.getScreenWidth() - 200 || null == mapStatus) {
MapStatus.Builder builder = new MapStatus.Builder();
mapStatus = builder.target(point).zoom(18.0f).build();
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
}
if (null == realTimeBitmap) {
realTimeBitmap = BitmapDescriptorFactory.fromResource(R.mipmap.icon_point);
}
addMarker(point);
}
/**
* 添加地图覆盖物
*/
private void addMarker(LatLng endPoint) {
if (null == mMoveMarker) {
OverlayOptions overlayOptions = new MarkerOptions().position(endPoint)
.icon(realTimeBitmap).zIndex(9).draggable(true);
mMoveMarker = (Marker) mBaiduMap.addOverlay(overlayOptions);
return;
}
if (null != lastPoint) {
moveLooper(endPoint);
} else {
mMoveMarker.setPosition(endPoint);
}
lastPoint = endPoint;
}
/**
* 移动逻辑
*/
public void moveLooper(LatLng endPoint) {
mMoveMarker.setPosition(lastPoint);
mMoveMarker.setRotate((float) CommonUtil.getAngle(lastPoint, endPoint));
double slope = CommonUtil.getSlope(lastPoint, endPoint);
// 是不是正向的标示(向上设为正向)
boolean isReverse = (lastPoint.latitude > endPoint.latitude);
double intercept = CommonUtil.getInterception(slope, lastPoint);
double xMoveDistance = isReverse ? CommonUtil.getXMoveDistance(slope) : -1 * CommonUtil.getXMoveDistance(slope);
for (double latitude = lastPoint.latitude; latitude > endPoint.latitude == isReverse; latitude =
latitude - xMoveDistance) {
LatLng latLng;
if (slope != Double.MAX_VALUE) {
latLng = new LatLng(latitude, (latitude - intercept) / slope);
} else {
latLng = new LatLng(latitude, lastPoint.longitude);
}
mMoveMarker.setPosition(latLng);
}
}
public TextView getTravelStateTv() {
return travelStateTv;
}
@Override
public void sendMessage(int messageType, Object messageInfo) {
Message message = null;
switch (messageType) {
case Constants.ENTITY_LIST:
message = realTimeLocHandler.obtainMessage(Constants.ENTITY_LIST);
message.obj = messageInfo;
break;
case Constants.REAL_TIME_LOC:
message = realTimeLocHandler.obtainMessage(Constants.REAL_TIME_LOC);
message.obj = messageInfo;
break;
}
realTimeLocHandler.sendMessage(message);
}
@Override
public void onPause() {
// TODO Auto-generated method stub
mapView.onPause();
super.onPause();
}
@Override
public void onResume() {
// TODO Auto-generated method stub
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
mapView.onDestroy();
if (null != mMoveMarker) {
mMoveMarker.remove();
}
realTimeBitmap = null;
super.onDestroy();
}
}
这里只有开始和停止,因为我没有把那块代码带回宿舍,谁要的话私聊我
今天就这样,明天接下写,晚安大家