资源描述
河北农业大学
本科毕业论文(设计)
题 目:基于Android的家庭理财通软件的设计——支出管理模块
目 录
摘要 1
1 引言 2
1.1 Android安全性能分析 2
2 Android的相关技术介绍及分析 3
2.1Linux内核 3
2.2中间件 3
2.3 应用程序框架 4
2.4应用程序 4
3 Android应用程序结构剖析 5
3.1 Android的API 5
3.2Android应用程序结构解析 6
3.2.1activity 6
3.2.2意图接收器(也成为广播接收器) 6
3.2.3服务 7
3.2.4 content provider 7
3.3 Intent 7
3.4 Android活动的生命周期 7
3.4.1活动的生命状态 7
3.4.2 活动的运作流程 8
4 Android家庭理财软件支出部分的设计与实现 9
4.1 研究目标 9
4.2 需求分析 9
4.3 UI界面设计 10
4.4 程序模块设计 10
4.5 软件功能图 12
4.6 文件结构与用途 12
4.7 程序主要代码 13
4.8 用户界面 17
5 总结 21
参考文献 22
基于Android平台的家庭理财软件
摘要:随着智能手机被越来越多的人所接受,手机已经慢慢从一个通讯工具变成了我们随身的百宝箱,从最早的电话短信功能,发展到如今的拍照、摄像、上网、玩游戏,手机,已经变成了堪比电脑的存在。因此,手机的贴身应用开发将会有很大的发展空间,本次设计的家庭理财软件就是其中之一。Android平台提供给用户非常方便的数据的随时记录、查询、计算与统计功能,这为家庭理财软件的设计实现与应用推广提供了良好的平台。另外,android作为一款免费的开发平台,开发成本基本为0,为软件的普及提供了良好的基础。
不过,正如android是开源的系统,其系统安全性必然存在很多问题,如何避免私人数据丢失,如何保证个人数据安全就成为了每个软件开发者不得不面对的问题。
本文针对目前android系统的安全性、系统框架进行了简要分析,并针对安全问题提出了自己的解决办法。基于系统框架以及各组件的学习研究,设计开发了家庭理财软件的支出部分设计。本系统界面简洁,操作简单,具有良好的可扩展性和可维护性。经测试,系统可以在android 4.0手机完美稳定运行,满足软件用户所需的账本记录查询等功能。
关键词:Android;Java;家庭理财;Intent;布局;数据安全
1 引言
目前随着移动设备越来越普及以及移动设备的硬件的提升,移动设备的功能越来越完善,移动设备的系统平台也日渐火热起来。目前国内最常见的移动开发平台有Symbian,iPhone,Windows Phone以及当下异军突起的Android。目前为止国内已经有很多Android系统的用户。截止至今Android系统的国内市场占有率已经过已超过七成,可见Android系统的用户基数之大。但是对于Android系统的应用和开发在国内仍然属于起步和探索阶段。急需要大量的相关技术和人员的投入。
下面首先介绍一下Android系统的安全性以及框架结构。Android是基于Linux内核的软件平台和操作系统,是Google在2007年11月5日公布的手机系统平台,早期由Google开发,后由(Open Handset Alliance)开发。它采用了软件堆层(Software stack,又名以软件叠层)的架构,主要分为三部分。低层以Linux核心工作为基础,只提供基本功能;其他的应用软件则由各公司自行开发,以Java作为编写程式的一部分。
因为兴趣和挑战,我开始学习android编程,通关指导老师的帮助完成了安卓家庭理财软件。希望通过这篇论文的研究,展示我在校期间学习与实践的成果,希望给在农大四年的本科学习交上一份圆满的答卷。
1.1 Android安全性能分析
(1)Android内核存在大量漏洞,已有许多漏洞利用工具
由于Android系统平台自身开源性的特征,它已经成为现今黑客重点攻击目标。黑客针对现有漏洞,已开发出众多的漏洞利用工具,其中窃取用户隐私、恶意扣费等行为的工具和木马类型的恶意软件占到多数。此类程序,病毒会自动联网、在系统后台启动恶意进程,窃取手机中的隐私内容,直接威胁到用户的安全。
(2)Android 缺乏功能强大的病毒防护或者防火墙现阶段,专业从事手机系统防护和手机病毒查杀的公司还比较少见,公众手机防病毒意识还不强,Android系统作为基于Linux的智能手机平台,其病毒防护或防火墙功能较弱,目前基于Android平台的病毒变种也正在呈集群式爆发。从发现“给你米”、“安卓吸费王”病毒到现在,其变种已多达63个,波及用户数超过90万。并且,Android平台病毒的某些特征也在逐渐凸显,病毒作者所植入的软件也越来越有名,近期被查杀的“红透透(HongTouTou)病毒”就是伪装在知名手机游戏软件“机器人塔防”中,用来盗取用户私人信息的病毒,已造成较大破坏。
(3)Android 应用软件缺乏安全审核及监管保护Android用户远离恶意应用程序的是一种基于“功能”的安全模式。每个Android应用程序必须告知手机的操作系统它需要的功能。当你安装应用程序时,操作系统列出应用程序需要运行的功能。你可以判断这是否与应用程序声称的相符。基于功能的系统具有由操作系统强制执行的优势。应用程序根本不可能说一套做一套。它也不依赖于人工筛选的警觉。这样做的问题在于,无法确保应用程序的行为会与其被给予的信任相称。
功能限制并不能保护用户免受这一类的攻击,因为流氓软件要求的权限与合法应用程序是一样的:也就是,接收一个人的用户名和密码,并通过互联网与远程服务器沟通这些信息的权限。基于功能系统的另一个问题在于,它需要用户仔细考虑安全问题。许多用户难以准确评估他们想要下载运行的软件风险——即便当他们怀疑软件可能是恶意软件时。Android手机系统自身的验证机制相对薄弱,如其只能保证对下载程序的稳定性、数据完整性进行检测,无法验证Android手机软件的来源,以及对安装后程序可能存在的行为进行判定,故无法对安全性进行保证。
(4)Android 软件开发工具包(SDK) 存在较多安全隐患
Android SDK 自测试阶段就不断暴露出例如远程控制漏洞、整数溢出和浏览器在处理GIF、BMP和PNG图像时的数据溢出等各种类型的漏洞,攻击者可利用这些漏洞执行自己的恶意代码,进而完全控制装有Android软件的手机。如果补丁未及时更新,及易在这方面造成较大危害。
2 Android的相关技术介绍及分析
2.1 Linux内核(Linux Kernel)
Android运行在linux kernel 2.6之上,但是把linux内受GNU协议约束的部分做了取代,这样在Android的程序可以用于商业目的。
Linux 内核是硬件和软件层之间的抽象层。
2.2 中间件
中间件包括两部分:核心库和运行时(libraries & Android runtime)
核心库包括,SurfaceManager 显示系统管理库,负责把2D或3D内容显示到屏幕;Media Framework 媒体库,负责支持图像,支持多种视频和音频的录制和回放;SQlite 数据库,一个功能强大的轻量级嵌入式关系数据库;WebKit 浏览器引擎等。
Dalvik虚拟机:区别于Java虚拟机的是,每一个Android 应用程序都在它自己的进程中运行,都有一个属于自己的Dalvik 虚拟机,这一点可以让系统在运行时可以达到优化,程序间的影响大大降低。Dalvik虚拟机并非运行Java字节码,而是运行自己的字节码。
2.3应用程序框架(Application Framework)
丰富而又可扩展性的视图(Views),可以用来构建应用程序,它包括列表(lists),网格(grids),文本框(text boxes),按钮(buttons),可嵌入的web浏览器。
内容提供者(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库),或者共享它们自己的数据。
资源管理器(Resource Manager)提供非代码资源的访问,如本地字符串,图形,和布局文件(layoutfiles)。
通知管理器(Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。
活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。
2.4 应用程序 (Applications)
Android系统会内置一些应用程序包,包括email客户端、SMS短消息程序、日历、地图、浏览器、联系人管理程序等。所有的应用程序都是使用JAVA 语言编写的。下图用来显示android架构的五个部分:
图2-1 安卓架构的五个部分
3 Android应用程序结构剖析
3.1 Android的API
Android API主要包含了以下几个部分:
(1)AndroidManifest.xml
AndroidManifest.xml是系统的控制文件,用于对软件所有用到的activity、service等进行注册,并进行简单的属性设置。另外,该文件也记录了软件所需要的系统使用权限。
(2)Activity
翻译过来就是活动。也就一个完整的操作过程,这个过程可以用来显示一个界面,接受一些数据,或者只是单纯的运行一些方法。
(3)View
视图是主要用于显示的图形界面。Android的图形界面基本上都是由各种视图组件构成,如listview、imageview等,视图的存在让android的图形界面设计更简单丰富。另外,开发者也可以自定义视图,以实现开发者想得到但系统未自带的效果。
(4)Intent
也可以称之为意图,实际上它就是一个简单地消息对象,表示程序将要运行到的位置,可以是一个视图,也可以是一个service,并且可以将一些简单的消息在跳转的时候进行传送,也可以通过bundle传输一些稍微复杂的数据对象。
(5)Service
主要是用来承担一些后台的操作过程。作为一款智能的操作系统,多线程以及后台必不可少,这就是service的存在。它可以用于后台运行一些过程,比如音乐播放,也可以用于永久监听一些事件,比如监听短信。
(6)Message
Android的特色之一,可以将一些后台接受到的消息,比如短信,提示更新等用小图标显示到通知栏上,用户可以通过下拉点击的过程对消息进行处理。
(7)Content Provider
主要是用于程序间的数据共享,比如可以从电话应用中调用联系人信息,短信发送也可以调用联系人信息。
3.2Android应用程序结构解析
Android应用程序由以下四大组件构成:
①activity
②Broadcast Receiver
③service
④content provider
但程序与这四大组件并不是对等关系,并不是要求每个应用都必须包含这四大组件。成俗可根据需求选择需要用到的组件,但必须注册到主文件中。
3.2.1Activity
Activity是android应用开发最常用到的组件之一。它的存在主要是为了显示应用软件的图形界面。Activity之间主要是通过intent进行跳转组合。
3.2.2意图接收器(也称为广播接收器)
可以被注册在AndroidManifest.xml文件中,同时也可以在代码中使用Context.registerReceiver()来注册,主要是程序用来处理一些外部提醒。比如接收到短信时候程序进行的操作。
3.2.3服务
主要是用于后台,没有图形界面,具有长生命周期。
3.2.4 content provider
一个专门用于不同应用间共享程序的工具类。每个应用都可以访问到别的应用用该类处理提供的数据信息。
3.3 Intent
由上文综述可知Android应用程序主要包含四大组件。但每个组件之间都是相互独立存在,而完成任何一个复杂的应用处理过程都不能能只用到一个组件,这时候我们就需要一个工具来将这些组件有机的组合到一起,我们使用的这个工具就叫做Intent,也称之为意图。通过这个工具,我们可以实现activity的跳转,实现service的开启,系统功能的调用,简单数据的传输等。
例如,在本次的毕业设计中,需要用到gps模块,但是打开系统设置的gps模块相对比较复杂,所以在登陆界面可以通过一个intent来定位系统的gps设置界面,然后调用startActivity(intent)方法来开启系统的gps设置。
3.4 Android activity的生命周期
Android系统作为一款针对手机、平板的操作系统,智能化是其主要特色。因此必然会引入类似于生命周期的概念。生命周期的存在,让界面的跳转、返回变得灵活,让多线程、后台能方便顺畅的引入。下面就纤细说一下android生命周期的各个状态以及转换过程:
3.4.1activity的生命状态
Android的虚拟机是使用堆栈管理。主要有四种状态:
(l)活动状态
活动状态指的是当前activity,就是手机上边显示出来的界面,该界面有且只有一个,不会出现同时有两个界面处于活动状态
(2)暂停状态
当有一些弹出框出现,活动界面变暗处于底层并且不可操作,此时的界面状态就是暂停状态
(3)停止状态
一个新的activity处于活动状态,原activity不可见,此时原activity就是处于停止状态,但仍然处于存在状态,可以被消息唤醒
(4)已回收或未启动状态
调用finis()方法或者因内存不足时一些处于停止状态的会自动被虚拟机回收后就处于该状态,不能被唤醒。
图3-1 Android活动生命周期
3.4.2 活动activity的转换过程
(l)启动
启动一个activity的基本流程为onCreate一>onstart一>onResume。该流程首先分配资源给这个activity(创建状态),然后将activity的内容显示到屏幕上(启动状态);在一切就绪后,取得屏幕的控制权(恢复状态),用户可以开始使用这个程序。
(2)调用
调用另一个activity的基本流程为onpause(l)一>onCreate(2)一>onstart(2)一>0nResume(2)一>onStop(l)。该流程首先冻结原来的activity,再交出屏幕控制权;直到activity2完成一般启动流程后,activity1才会被停止。
(3)返回
回到原来activity的基本流程为onPause(2)一>onRestart(1)一>onstart(l)一>onResume(1)一>onstop(2)一>onDestroy(2)。另外按返回键也可以回到原来的activity。
(4)退出
退出结束的基本流程为onPause一>onStop一>onDestroy。如果程序中有直接调用finish方法来关闭activity的话,系统会跳过先冻结的阶段,直接暂停,停止,然后销毁。
(5)回收(finish)后再次启动
回收后再启动的基本流程为oncreate一>onstart一>onresume。如果被回收掉的activity一旦又重新被调用时,会像一般启动一样再次调用activity的onCreate方法。
当在模拟器上已经执行过多个应用程序,只要按下返回键,就会开启最近一次开启过的activity。所以如果要让再次被创建的activity跟原来开启过的一样,那么在activity之间切换时,就要保存资料:即在每次activity运行到暂停或停止状态时先保存资料,然后在创建时将资料读出来。
4 Android家庭理财软件支出部分的设计与实现
4.1 研究目标
(1) 熟悉使用android软件开发流程,养成良好的软件开发习惯
(2) 学习使用android的多种组件的使用。
(3) 对数据安全进行基本的分析了解,初步养成随时注意数据安全的习惯
(4)熟悉java环境对android数据库的操作过程
本软件是采用Eclipse的环境开发,基于android 4.03版本完美测试运行。
4.2 需求分析
本软件是Android平台家庭理财工具,启动程序后应该可以对日常每一天的收入支出进行查询与统计,并且要有用户个人信息的基本安全加密;
由此可得项目需求:
(1) 首先要实现用户登陆管理,只有拥有权限的用户才能登陆应用,保证用户的信息安全;
(2) 要有对用户进行修改新增的功能,并且对数据进行加密处理;
(3) 要有支出记录功能,记录支出时间以及面额,坐标获取功能让你知道都是在哪儿消费过,照片记录能让你记录个人都在哪儿消费过;
(4) 要拥有对记录数据的查询功能;
(5) 在查询的同时要拥有对保存数据进行删除以及修改的功能;
(6) 关于模块,记录软件版本及发行等相关信息;
(7) 帮助模块,提供对软件功能及大概使用方法的综合描述。
4.3 UI界面设计
根据需求分析可以知道,应用程序应包含十二个用户界面,在这一步进一步分析每一个用户界面的基本构成,也就是每一个界面的结构框架。
在登陆界面,需要有两个输入框,分别输入用户名跟密码,然后要有登陆按钮,又因为应用需要用到gps模块,所以还需要一个按钮进行连接到gps开启界面,使软件应用更加方便。
登陆完成后,跳转到主界面,因为主界面功能较多,所以采用GridView+imageview布局,是界面统一简单,也就是网格布局
支出记录界面,设计为从上到下的线性布局,分别记录当前坐标,时间,消费金额以及消费场景照片,在最下排放入功能按钮
查询界面,用listview列表显示以往的记录信息,同步实现对每一条数据的查询修改功能。
用户新增界面,线性提供三个文本输入框,分别用来输入用户名跟密码以及密码确认,最下排放功能按钮
用户修改界面,要比新增界面增加一个文本框,用于输入用户原密码。
关于以及帮助界面基本上结构相同,都由一个大的文本区域以及最下排的功能按钮构成
4.4 程序模块设计
从功能需求上分析可以看出,整个应用程序应划分为11个模块,分别是登陆、功能选择、记录、查询方式选择、记录修改、记录查看、照片查看、用户新增、用户修改、关于、帮助
登陆是应用软件打开后的第一个界面,用于验证用户是否有对软件的使用权限;功能选择是整个软件的核心,其中包括了软件的各种主要功能;记录用于对支出情况进行详细数据采集记录;查询方式选择用于选择所要查询的内容;记录修改用于更改某一次消费信息的具体数额;记录查看用于显示全部的支出信息;照片查看用于查看某一次消费信息的照片情况;用户新增用于对新用户赋予软件的使用权限;用户修改用于修改某一现存用户的密码;关于用于显示软件版本信息以及发行人;帮助用于对软件基本功能以及使用方法进行介绍;
根据如上功能,对数据库进行设计,共需要user表、out表;分别用于记录用户信息以及支出信息数据,user表包括(id,name,password),out表包括(id,out,x,y,time,pic,name)
在完成用户界面设计、数据库设计和模块设计后,至此程序设计阶段基本完成。
4.5 软件功能图
《家庭理财》软件支出
登陆
功能选择
支出记录
记录查询
定位信息
便签管理(预留)
基础信息录入(预留)
数据备份(预留)
数据同步(预留)
关于
新用户
用户修改
帮助
退出
记录修改
记录删除
照片查看
查询方式
图4-1 软件功能图
4.6 文件结构与用途
建立项目,项目名称为“MyMoneyManager”,选择开发版本sdk为4.03,项目工作空间为“com.ymtq.hu”,确定之后系统会自动生成一个项目工作空间。
Android的资源文件保存在/res的子目录中。其中、/res/anim目录中保存的是产生动画效果的XML文件,/res/drawable/目录中保存的是图像文件,/res/values目录中保存的是用来自定义字符串和颜色的文件,/res/xml目录中保存的是XML格式的数据文件。所有在程序开发阶段可以被调用的资源都保存在这些目录中,具体每个资源文件的用途可以参考表4.2:
资源目录
文 件
说 明
anim
Grallery_in.xml
图片进入效果
left_in.xml
画面转换位置移动动画效果(从左进入)
left_out.xml
画面转换位置移动动画效果(从左移出)
right_in.xml
画面转换位置移动动画效果(从右进入)
left_out.xml
画面转换位置移动动画效果(从右移出)
drawable
icon1.png
这个文件夹里是工程里所用的图片
icon2.png
icon3.png
……
layout
Main.xml
“功能选择”的布局
Login.xml
“登陆”的布局
Find.xml
“搜索”的布局
...
还有很多的layout,不赘述
values
style.xml
保存样式的XML文件
strings.xml
保存字符串的XML的文件
drawbles.xml
AppWidget的属性文件
表4.2 资源文件名称与用途
4.7 程序主要代码
(1) Login.java的部分代码:
Button login, cancel;
private DataBaseHelper dh;
String name, password;
EditText Name, Password;
int flag = 1;
int mflag = 1;
int mflag2 = 1;
大类中首先就是生命组件跟变量,android是一个组件式开发环境,以组件修改套接开发为主;
public static String MD5(String str) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
return "";
}
char[] charArray = str.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) {
byteArray[i] = (byte) charArray[i];
}
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
MD5算法加密,用于对用户名密码加密保存。这么做主要是因为sqlite数据库本身安全性不高,访问权限基本等于没限制。
手写一个继承SQLiteOpenHelper的数据库助手类DataBaseHelper,通过该类进行数据库连接初始化工作,通过new出来的DataBaseHelper对象进行数据库操作
数据库操作主要代码:
SQLiteDatabase db = dh.getReadableDatabase();
String[] columns = {
DataBaseHelper.ID, DataBaseHelper.NAME,
DataBaseHelper.PASSWORD };
Cursor c = db.query(DataBaseHelper.TABLE_USER, columns, null,null, null, null, null);
while (c.moveToNext()) {
}
}
c.close();
db.close();
(2) 功能选择界面的部分代码:
Button btn_new,btn_about,btn_up,btn_help;
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {}
从代码可见,该界面主要实现的就是按钮功能,用来作为软件各功能实现的纽带;GridView采用一个自定义的布局填充;
(3)记录中的部分代码
Criteria criteria = new Criteria();// 对gps获取信息方式进行设置
criteria.setAccuracy(Criteria.ACCURACY_FINE);// 精度
criteria.setAltitudeRequired(false);// 是否要高度信息
criteria.setBearingRequired(false);// 是否要方位信息
criteria.setCostAllowed(true);// 是否需要产生费用
criteria.setPowerRequirement(Criteria.POWER_LOW);// 耗电量设置了首先对gps模块进行设置,因为该功能的实现要启用gps模块,获取定位信息
protected void camera() {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
picpath = System.currentTimeMillis() + ".jpg";
Uri uri = Uri.fromFile(new File("/sdcard/" + picpath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, REQUESTCODE);
}
调用系统的照相接口,实现照片采集功能,并自动保存到内存卡上边。
Toast.makeText(getApplicationContext(), "已保存完成",
Toast.LENGTH_LONG).show();
用Toast提示照片保存完成
(4) 查询中的部分代码。
private List<Manager> find(){
dh = new DataBaseHelper(this);
SQLiteDatabase db = dh.getReadableDatabase();
String[] columns = { DataBaseHelper.IN, DataBaseHelper.TIME,
DataBaseHelper.PIC,DataBaseHelper.X,DataBaseHelper.Y };
Cursor c = db.query(DataBaseHelper.TABLE_USER_IN, columns, null, null,null, null, null);
List<Manager> users = new ArrayList<Manager>();
Manager e = null;
while (c.moveToNext()) {
e = new Manager();
e.setIn(c.getDouble(0));
e.setTime(c.getString(1));
e.setPic(c.getString(2));
e.setX(c.getDouble(3));
e.setY(c.getDouble(4));
users.add(e);
}
c.close();
db.close();
return users;
}
查询方法,查询返回一个list集合,包含数据库表内的全部数据信息
(5) 新用户的部分代码:
if (userpassword.equals(testpassword)) {
SQLiteDatabase db = dh.getWritableDatabase();
User user = new User(MD5(userName.getText().toString()),
MD5(userpassword));
ContentValues values = new ContentValues();
values.put(DataBaseHelper.NAME, user.getName());
values.put(DataBaseHelper.PASSWORD, user.getPassWord());
db.insert(DataBaseHelper.TABLE_USER, null, values);
db.close();
Toast.makeText(NewUser.this, "数据插入成功",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(NewUser.this, "数据未插入成功",
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(NewUser.this, "两次输入的密码不一致,请重新输入",
Toast.LENGTH_LONG).show();
}
首先验证两次输入的密码是否一致,然后将用户信息插入user表,并用toast对操作结果进行提示
(6) 用户修改的主要代码:
SQLiteDatabase db1 = dh.getWritableDatabase();
User user = new User(name, MD5(userPassword
.getText().toString()));
ContentValues values = new ContentValues();
values.put(DataBaseHelper.NAME, user.getName());
values.put(DataBaseHelper.PASSWORD,
user.getPassWord());
String whereClause = DataBaseHelper.ID + "=?";
String[] whereArgs = { String.valueOf(c.getInt(0)) };
db1.update(DataBaseHelper.TABLE_USER, values,
whereClause, whereArgs);
Toast.makeText(UserUp.this, "数据修改成功",
Toast.LENGTH_LONG).show();
c.close();
db.close();
db1.close();
主要实现的是数据库的更新,对user表的用户密码进行修改
(7) AndroidManifest.xml主要代码:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
<uses-permission android:name="android.permission.U
展开阅读全文