您的位置:首页 > 移动开发

开发一个基于 Android系统车载智能APP

2017-11-07 15:52 519 查看
很久之前就想做一个车载相关的app、需要实现如下功能:

    (1)每0.2秒更新一次当前车辆的最新速度值。
    
(2)可控制性记录行驶里程。
    
(3)不连接网络情况下获取当前车辆位置。如(北京市X区X路X号)
    
(4)实时快速获取车辆运动方向。
    
(5)获取当前太空卫星数量以及GPS状态。

以上功能不需要连接网络、不需要开蓝牙、APP显示名字等可定制;

条件是有个大屏的Android系统车载导航。

好了、实现上面的第一步是需要一个汽车仪表盘的source、网上搜索了一下是有的,所以直接下载了;详细请点击:

/*
* Project Name:PGSL
* File Name:SpeedControlView.java
* Package Name:chenfei.Server
* Date:2017-4-16下午1:51:19
* Copyright (c) 2017, xx@163.com xx  Rights Reserved.
*
*/
package chenfei.Server;

/*
* ClassName:SpeedControlView
* Function:   ADD FUNCTION.
* Reason:     ADD REASON.
* Date:     2017-4-16 下午1:51:19
* @author   xx
* @version
* @since    JDK 1.6
*/

import cgenfei.gz.cn.ComData;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;

public class SpeedControlView extends View implements Runnable {

private float radius, sRadius; // 圆的半径
private float screenWith, screenHeight;// 屏幕宽高
private float pointX, pointY;// 圆xy坐标
private float baseX, baseY;

private Paint mPaint, speedAreaPaint, textPaint;
private float textScale;
// 速度范围的2个扇形外切矩形
private RectF speedRectF, speedRectFInner;
private float mDensitydpi = 0;

// 设置速度 并重绘视图
public void refresh() {
postInvalidate();
}

public SpeedControlView(Context context) {
super(context);
}

public SpeedControlView(Context context, AttributeSet attrs) {
super(context, attrs);

screenWith = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();

screenHeight = ((Activity) context).getWindowManager().getDefaultDisplay().getHeight();

DisplayMetrics displayMetrice = getResources().getDisplayMetrics();

screenWith = displayMetrice.widthPixels;

screenHeight = displayMetrice.heightPixels;

mDensitydpi = (float) displayMetrice.densityDpi / 320;

if (mDensitydpi < 1)
mDensitydpi = 1;

setLayerType(LAYER_TYPE_SOFTWARE, null);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(5 * mDensitydpi);

textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(Color.parseColor("#76EE00"));
Typeface typeface = Typeface.createFromAsset(context.getAssets(),"kt.ttf");
textPaint.setTypeface(typeface);

radius = screenHeight / 2 - 8;
pointX = screenWith / 2;
pointY = screenHeight / 2;
sRadius = radius - 60 * mDensitydpi;

// 设置抗锯齿
speedAreaPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
speedAreaPaint.setAntiAlias(true);
// 设置画笔样式
speedAreaPaint.setStyle(Paint.Style.FILL);
// 设置速度范围扇形的渐变颜色
Shader mShader = new LinearGradient(0, 0, 100, 100, new int[] {0x7001EC9, 0xBF001EC9, 0xFF001EC9 }, null,Shader.TileMode.CLAMP);

speedAreaPaint.setShader(mShader);

// 初始化速度范围的2个扇形外切矩形
speedRectF = new RectF(pointX - radius + 10 * mDensitydpi, pointY
- radius + 10 * mDensitydpi,
pointX + radius - 10 * mDensitydpi, pointY + radius - 10
* mDensitydpi);

speedRectFInner = new RectF(pointX - radius / 2, pointY - radius / 2,
pointX + radius / 2, pointY + radius / 2);
}

public SpeedControlView(Context context, AttributeSet attrs,int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制速度范围扇形区域
speedAreaPaint.setColor(0x7E3F51B5);
drawSpeedArea(canvas);
drawSpeedCircle(canvas);
drawScale(canvas);
for (int i = 0; i < 8; i++) {
drawSpeedText(canvas, i * 6);
}
}

// 速度刻度值
private void drawSpeedText(Canvas canvas, int value) {
double hudu = 0;
textPaint.setTextSize(25 * mDensitydpi);
textScale = (int) (textPaint.descent() + textPaint.ascent()) / 2;
String TEXT = String.valueOf(value * 5);
hudu = (2 * Math.PI / 360) * 6 * (value + 39);
baseX = (int) (pointX + Math.sin(hudu) * sRadius - textScale / 2 - textPaint.measureText(TEXT) / 1.5);
baseY = (int) (pointY - Math.cos(hudu) * sRadius - textScale / 2);
canvas.drawText(TEXT, baseX, baseY, textPaint);
}

private void drawSpeedCircle(Canvas canvas) {
mPaint.setColor(0xFF343434);
canvas.drawCircle(pointX, pointY, radius, mPaint);

// 外圈2个圆
mPaint.setStrokeWidth(4 * mDensitydpi);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0xBF3F6AB5);
canvas.drawCircle(pointX, pointY, radius, mPaint);
mPaint.setStrokeWidth(3 * mDensitydpi);
canvas.drawCircle(pointX, pointY, radius - 10 * mDensitydpi, mPaint);

// 内圈2个圆
mPaint.setStrokeWidth(5 * mDensitydpi);
mPaint.setColor(0xE73F51B5);
canvas.drawCircle(pointX, pointY, radius / 2, mPaint);
mPaint.setColor(0x7E3F51B5);
canvas.drawCircle(pointX, pointY, radius / 2 + 5 * mDensitydpi, mPaint);

// 速度显示lab
textPaint.setTextSize(85 * mDensitydpi);
float textWidth = textPaint.measureText(ComData.spdnow + "");
baseX = (int) (pointX - textWidth / 2);
baseY = (int) (pointY + Math.abs(textPaint.ascent() + textPaint.descent()) / 4);
canvas.drawText(ComData.spdnow + "", baseX, baseY, textPaint);

//速度单位lab
textPaint.setTextSize(20 * mDensitydpi);
textWidth = textPaint.measureText("Km/h");
baseX = (int) (pointX - textWidth / 2);
baseY = (int) (pointY + Math.abs(textPaint.ascent()+ textPaint.descent()) / 4);
canvas.drawText("Km/h", baseX, baseY + 50 * mDensitydpi, textPaint);

//地理位置lab
textPaint.setTextSize(20 * mDensitydpi);
textWidth = textPaint.measureText(ComData.ads);
baseX = (int) (pointX - textWidth / 2);
baseY = (int) (pointY * 8 / 5) - 2;
canvas.drawText(ComData.ads, baseX, baseY + 50 * mDensitydpi, textPaint);

}

private void drawScale(Canvas canvas) {
for (int i = 0; i < 60; i++) {
if (i % 6 == 0)
canvas.drawLine(pointX - radius + 10 * mDensitydpi, pointY,pointX - radius + 50 * mDensitydpi, pointY, mPaint);
else
canvas.drawLine(pointX - radius + 10 * mDensitydpi, pointY,pointX - radius + 30 * mDensitydpi, pointY, mPaint);

canvas.rotate(6, pointX, pointY);
}
}

/**
* 绘制速度区域扇形
*/
private void drawSpeedArea(Canvas canvas) {
float degree;
if (ComData.spdnow < 210) {
degree = (float) (ComData.spdnow * 1.2);
} else {
degree = 252;
}

canvas.drawArc(speedRectF, 144, degree, true, speedAreaPaint);
mPaint.setStyle(Paint.Style.FILL);
//mPaint.setColor(Color.BLACK);
canvas.drawArc(speedRectFInner, 144, degree, true, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
}

@Override
public void run() {
/*while (true) {
try {
Thread.sleep(40);
refresh();
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
}
}


View Code

ok 到了这里应该有一个华丽的分割线了

---------------------------------------------------------------------------------------

以上可以实现仪表盘以及获取GPS等数据的功能了。

下面是要获取该lng lat经纬度所在地名称。

3.6- 抓取XX度的地图经纬度数据。

调用api,然后是这样的获取经纬度

for(lng){
for(lat){
get_xx_api(lng,lat,sign);
}
}


遍历整个中国大地的经度以及纬度,然后会得到一堆json、解析后存储到db文件中、本人存储的方式是这样的做法。

sql="insert into GPS117(lng,lat,ads) values (117.289,40.65,'北京市密云县Y264')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,40.61,'北京市密云县Y257')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,40.17,'北京市平谷区韩海路')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,40.09,'天津市蓟县砖蓟路')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,40.05,'天津市蓟县S1(津蓟高速)')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,40.01,'天津市蓟县许邦路')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,39.890,'天津市蓟县东毛路')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,39.770,'天津市宝坻区G1(京哈高速)')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,39.730,'天津市宝坻区西关街')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,39.690,'天津市宝坻区开元路')";   db.execSQL(sql);
sql="insert into GPS117(lng,lat,ads) values (117.289,39.650,'天津市宝坻区国泰路')";   db.execSQL(sql);


这样的数据很多,获取数据过程中lng和lat的自增因子越小导致代码越多;当然你可以用程序生成、解放双手干其TA的。

有这些代码后就可以在app第一次安装启动时候执行到本地的db中了、是不是很完美呢、解决了不需要网络的大难题。

3.7- DatabaseHelper.java

该类就是程序安装启动时候执行的函数功能类了。

/*
* Project Name:PGSL
* File Name:DatabaseHelper.java
* Package Name:xx.db
* Date:2016-8-16下午1:16:07
* Copyright (c) 2016, xx@163.com xx  Rights Reserved.
*
*/
package xx.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/*
* ClassName:DatabaseHelper
* Function:   ADD FUNCTION.
* Reason:     ADD REASON.
* Date:     2016-8-16 下午1:16:07
* @author   xx
* @version
* @since    JDK 1.6
*/
public class DatabaseHelper extends SQLiteOpenHelper {
static String name = "xxxxxxxxxxx4dwd6f9w4f4wf4ew5f4ew54f.db";
static int dbVersion = 1;

public DatabaseHelper(Context context) {
super(context, name, null, dbVersion);
}

// 只在创建的时候用一次
public void onCreate(SQLiteDatabase db) {
CommonTab tab = new CommonTab();
tab.CreateTable(db);
tab = null;

CommonDBBASE base = new CommonDBBASE();
base.AddDATA(db); // BASE
base = null;

CommonCNOne one = new CommonCNOne();
one.AddDATA(db);
one = null;

CommonCNTwo two = new CommonCNTwo();
two.AddDATA(db);
two = null;

CommonCNThree three = new CommonCNThree();
three.AddDATA(db);
three = null;

CommonCNF fo = new CommonCNF();
fo.AddDATA(db);
fo = null;
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}


OK。。。。代码到此结束!

(4)实例图



好了、、、、这是目前本人实现的基于Android系统的车载app。

.

.

.

.

.

.

接下来本人琢磨着使用andrunio做一个类似于某宝上的抬头显示那玩意、、前提是接入汽车预留的接口(一般在方向盘)下面那玩意。

以上!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: