近端时间参加学校组织的科技创新活动,本人对于Android开发比较感兴趣,经过与导师商量结合自己的消防专业特色,决定以百度地图提供的API制作一款针对消防水源管理的水源管理系统。开发工具就使用最近比较流行的Android studio开发吧,具体安装也是照着网上通用的方法进行Android studio以及javaJDK安装。所使用数据库为轻量级数据库sqlite。以下便是我的开发工具列表:
Android studio3.0、sqlite3、javaJDK1.8、试验机就是Android真机试验、百度地图API7.5.0
大多数资料来源便是在与大神们的CSDN博客中的经验交流中学的,但是在学习中也遇到不少问题,也许是大神们的开发时间比较老,所以在应用到这些新版本时总会存在这样和那样的问题,经常会存在闪退、打不开、很多都是用eclipse进行完成,对于使用Android studio进行打开是也会有很多的麻烦。不过还好终于克服种种困难,这个基于百度地图的消防水源管理系统就客户端方面还算是完工了吧!写下这篇博客一来怕自己忘了,二来能够与大伙交流,共同进步,在开发的过程中有一些我还无法理解的bug,希望在与大伙的交流中得以解决。三来犒劳一下我自己,找点成就感。熬了不少夜。总得留下点东西不然太亏。废话说的有点多,总得一句话:这东西光看是学不会的,真的要自己动手操作。有些问题经过自己的处理东西才是自己的。基于百度地图的消防水源管理系统效果如下:
登录界面
进入界面
定位
火点添加
火点显示
水源添加
水源管理
火源显示
水源查询
热力图显示
附近查询
火点导航
接下来就是具体的开发:
一、工具以及资料准备:
1、功能界面划分:这个东西在软件系统开发过程中我感觉尤为重要,所谓磨刀不误砍柴工。软件的开发首先需要对于系统软件有一个大体的框架设计。这样在后期的软件制作过程中就不会因为思路混乱而乱了阵脚。甚至项目推倒重来。我最开始开发的时候没有注意到这个问题就走了弯路。我的功能界面划分差不多就是如上图一个个界面所示。地图显示在一个界面,其他的都是重新开一个界面。
2、图片资源准备:该部分内容主要就第一步的功能界面划分进行必要的资源准备。获取的方法很容易,百度就能查到很多。再由Photoshop进行简单的修改便可以了,该软件仅个人开发支撑大学生科技创新使用,应该不会涉及到侵权的问题吧。又不是拿来赚钱。
3、工具准备:首先是百度地图API的获取访问网站:http://lbsyun.baidu.com/便可进行获取相应的产品以及申请key。具体操作过程我会在之后的文章中进行介绍。
就这样软件开发的所有资源准备完毕,接下来就是具体开发了。
二、项目开发
1、创建项目(基本操作,不再累述)。
2、对于项目进行基本的百度地图API配置,在这里可以基本按照http://lbsyun.baidu.com/网站进行配置,但实践中Androidstudio进行开发过程中,只需要
1、打开project目录将BaiduLBS_AndroidSDK_Lib\libs中的jar包复制到project中app中libs中。
2、在src/main/目录下新建jniLibs目录,将BaiduLBS_AndroidSDK_Lib\libs里面那五个文件夹复制其中便可。
如图便可:
然后点击左侧圈圈按钮稍等便可。其他无需操作。切记
3、权限复制便可:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
//获取设备网络状态,禁用后无法获取网络状态
<uses-permission android:name="android.permission.INTERNET" />
//网络权限,当禁用后,无法进行检索等相关业务
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
//读取设备硬件信息,统计数据
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
//读取系统信息,包含系统版本等信息,用作统计
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
//获取设备的网络状态,鉴权所需网络代理
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//允许sd卡写权限,需写入地图数据,禁用后无法显示地图
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
//获取统计数据
<uses-permission android:name="android.permission.CAMERA" />
//使用步行AR导航,配置Camera权限
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
<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" />
<!-- SD卡读取权限,用户写入离线定位数据 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
4、新建MyApplication继承Application初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
SDKInitializer.initialize(this);
super.onCreate();
}(注意要在配置文件中进行声明
<application
android:name=".MyApplication"//不然会闪退。
5、设置BaseActivity对于一些重复的以及基本的操作进行统一处理,减少开发难度
本人的BaseActivity只要是为了简化吐司以及静态变量进行初始化方便各界面之间的信息交互代码如下:
public abstract class BaseActivity extends Activity {
private BroadcastReceiver receiver;//注册监听
public static String huozaileixing;//火灾类型
public static boolean huo=false;//是否显示火点
public static boolean sousuo=false;//是否显示搜索范围
public static String shuiyuanname="null";//待修改水源名字
public static int quanxian=0;//权限值
public static boolean jieshi=false;//权限解释
public static LatLng now=new LatLng(39.915112,116.403963);//当前地点
public static LatLng huodian=new LatLng(39.915112,116.403963);//当前火灾地点
public static LatLng shuiyuanchaxundian=new LatLng(39.915112,116.403963);//水源查询地点
public static double shuiyuansousuofanwei=100.00;//水源搜索范围
public static double suoxuyaoshuilaing=100.00;//水源所需要的量
public static String point="银行";//附近搜索地址
public static double FANWEI=1000.00;//附近搜索范围
public static boolean PTOT=false;//POI与TU之间转换
/**
* a为查询消火栓
* b为查询消防水池
* c为查询消防水鹤
*/
public static boolean a=false;
public static boolean b=false;
public static boolean c=false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerSDKCheckReceiver();
}
public void showlong(CharSequence arr){
Toast.makeText(BaseActivity.this,arr,Toast.LENGTH_LONG).show();
}
public void showshort(CharSequence arr){
Toast.makeText(BaseActivity.this,arr,Toast.LENGTH_SHORT).show();
}
private void registerSDKCheckReceiver(){
receiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if (SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR.equals(action)){
///showToast("网络错误");
showshort("网络错误");
}else if (SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR.equals(action)){
//showToast("KEY验证失败");
showshort("KEY验证失败");
}
}
};
IntentFilter filter=new IntentFilter();
//监听网络错误
filter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);
//监听百度地图SDK的key是否正确
filter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR);
registerReceiver(receiver,filter);
}
}
6、图像显示界面设计:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TuXianXianShiActivity">
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/leixin"
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="普通地图"
android:id="@+id/putong"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="实况地图"
android:id="@+id/shikuan"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="热力图"
android:id="@+id/reli"/>
</RadioGroup>
<EditText
android:layout_width="150dp"
android:layout_height="wrap_content"
android:hint="附近内容搜索"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:id="@+id/fujingsousuo"/>
<EditText
android:layout_width="150dp"
android:layout_height="wrap_content"
android:hint="搜索范围"
android:layout_centerHorizontal="true"
android:layout_below="@+id/fujingsousuo"
android:id="@+id/fujingfanwei"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="搜索"
android:textSize="20sp"
android:layout_below="@+id/fujingfanwei"
android:background="#37efbdbd"
android:id="@+id/sousuoanniu"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/huodui"
android:layout_alignParentBottom="true"
android:layout_marginLeft="60dp"
android:onClick="huodian"
android:layout_marginBottom="10dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/round"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:onClick="dingwei"
android:layout_marginBottom="20dp"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/xiaohuoshuan"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="60dp"
android:layout_marginBottom="10dp"
android:onClick="shuiyuan"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="实验"
android:layout_alignParentRight="true"
android:textSize="20sp"
android:id="@+id/shiyan"
android:layout_margin="5dp"
android:background="#30e9a6a6"
android:onClick="shiyan"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_margin="5dp"
android:text="火点导航"
android:background="#30e9a6a6"
android:layout_below="@+id/shiyan"
android:layout_alignParentRight="true"
android:onClick="daohang"/>
</RelativeLayout>
7、水源javabean制作:
public class ShuiYuan {
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getLeixin() {
return Leixin;
}
public void setLeixin(String leixin) {
Leixin = leixin;
}
public String getShuilian() {
return Shuilian;
}
public void setShuilian(String shuilian) {
Shuilian = shuilian;
}
public String getJindu() {
return Jindu;
}
public void setJindu(String jindu) {
Jindu = jindu;
}
public String getWeidu() {
return Weidu;
}
public void setWeidu(String weidu) {
Weidu = weidu;
}
private String Name;
private String Leixin;
private String Shuilian;
private String Jindu;
private String Weidu;
}
ps:其实Android studio对于javabean制作挺容易的不需要一个个敲,只要对着变量鼠标右键选择gengrate 再选择getter、setter就行。
7、sqlite数据库构建
public class MyOpenHelper extends SQLiteOpenHelper {
private Context mcontext;
public MyOpenHelper(Context context) {
super(context, "ditu.db", null, 1);
mcontext=context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table shuiyuan(_id integer primary key autoincrement,name varchar(20),leixing int,fanshi int,jingdu double,weidu double,shuilian double)");
Toast.makeText(mcontext,"创建成功",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
ps:切记当需要进行调用数据库是需要进行数据库声明以及初始化。不然会报错。初始化这一点我就经常忘记。
private MyOpenHelper myOpenHelper;
myOpenHelper=new MyOpenHelper(getApplicationContext());
8、考虑到说一大堆还不如直接将demo分享来的实际,我也偷个懒,因为实在有点多,只能部分显示。有些功能之间是进行实时交互的,所以分享就必须全部分享,这样文章就变得有点长了。如下图:
值得注意的一点就是
mBaiduMap = mMapView.getMap();//当进行地图操作是这句代码一定要带上。。。。不然会闪退
还有一点当进行全屏显示的时候就需要在配置文件中相应界面添加如下代码,但是该界面就继承AppCompatActivity不然会闪退。
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
最后注意一点在进行POI检索以及导航操作时会存在DrivingRouteLine不存在的情况,这里百度地图开发文档有说明:
注自V3.6.0起,原内置覆盖物相关类的代码开源
覆盖物开源代码中提供了一些基于基础覆盖而组合而成的高级覆盖物,包括用于显示poi数据,规划路线,公交详情路线的覆盖物。
OverlayManager/ PoiOverlay/ IndoorPoiOverlay/ IndoorRouteOverlay/ TransitRouteOverlay/ WalkingRouteOverlay/ BikingRouteOverlay/ DrivingRouteOverlay/ BusLineOverlay/ MassTransitRouteOverlay/ 以上源码可在BaiduMapsApiDemo工程中找到。
我们在相应位置进行复制粘贴到放置.java的地方便可。ps:这样运行还是会出错,找到出错地方,将显示图标语句改为资源图标便可例如:
.extraInfo(b)
.icon(BitmapDescriptorFactory
// .fromAssetWithDpi("Icon_line_node.png")));
.fromResource(R.drawable.icon_geo)));
将.fromAssetWithDpi("Icon_line_node.png")));注释改为.fromResource(R.drawable.icon_geo)));便可,这也是我的一个疑问点,不知道该如何解决。只能退而求其次这样了。
有点长,我就讲demo分享出来,大家讲demo导入到Android studio运行便可。链接为:
账号密码为111
就我的需求来说,已经基本达到我的需求,下一步目标便是构建服务器,以期待该app不限于只是单机版,而是能够进行不同用户之间的交互。就百度地图API开发来说,应该是一个相当综合的应用了,之后本人会针对百度地图开发各分功能进行总结,希望各位道友对于我的错误和不当之处及时指出,相互促进。Thanks♪(・ω・)ノ
该项目中还有一些bug我一直理解不了,希望有哪位道友看到我的文章之后能够不奢赐教。
bug如下:
1、在地图显示界面中按道理只要在onCreate中定义一次mBaiduMap = mMapView.getMap();就行了,但是实际应用中随着功能的增加,就会闪退,我只能每添加一个功能就在子方法中定义一次mBaiduMap = mMapView.getMap();
2、也是在图像显示界面随着功能的增加,我的导航和POI查询是后期添加的,就无法添加了,直接闪退,我只能再建一个界面。
项目开发总结:
1、规划是第一步,也是至关重要的一步,做好了后期会很顺。
2、所需资源尽可能放在一个文件夹中,方便查找。
3、资源文件管理条理清楚,对后期项目开发很重要,能够事半功倍。
4、有问题别退缩,像这种Android项目开发并不是无人区的圣地,前人都玩烂了的,只要多查资料基本都能解决。
5、项目开发不难,因为只是把前人的基础加以利用罢了,难就难在是否有好的想法。
项目中思考的问题:
1、我们都知道Androidstudio只能进行客户端开发,但是后台服务器的构建还是需要其他的工具。本人打算使用tomcat+Myeclipse进行构建。但是需要一个数据库进行后台数据库管理,请问可以使用sqlite吗?因为后台数据也不是很多,而且电脑正好装有sqlite。网上查到的很多都是MySQL。
2、租用服务器是否会存在安全性问题?