配置信息的一种方式,它只能存储基本数据类型。一个程序的配置文件仅可以在本应用程序中使用,或者说只能在同一个包内使用,不能在不同的包之间使用。实际上sharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data//shares_prefs下。
File是一种文件存储方式也是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。
具体问题具体分心,根据我们的需要与要求,本程序最终选定用SharedPreferences来存储我们的数据。我们将用户设置的安全密码、安全手机号、防盗功能开关状态、SIM卡的IMSI码等信息以键值对的形式存入其中进行保存。一个Value对应一个Key值,如图3.10所示,Key值便是我们所保存的数据信息,这样的保存方式既快捷又准确。
图 3.10 数据库存储方式
3.3.2 监听按钮事件服务
监听器是Android设计的一种监听模式,当用户执行了某些动作时,需要系统对这些动作做出相应的反应,那么这时就需要监听器来捕获这些来自用户的信息,将其传递给系统再做处理。
在我们的软件中将会运用大量的监听器,其中包括监听用户点击按钮事件、监听开机广播事件、监听短信广播事件等。
监听按钮事件,是将每个按钮绑定上一个监听器,用Button.setOnClickListener()方法来实现,当触发相应的监听器后我们就可以执行我们想要的操作了。
3.3.3 开机启动和短信广播服务
防盗应用开启后会在第一时间对手机的SIM卡进行检查,判断时候更换。那么这种监听开机需要另一项Android机制的支持来完成——广播机制。
在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播。图3.11就是一张广播的运行机制原理图。
图 3.11 Android广播机制
各种广播在Android 系统中运行,当系统/应用程序运行时便会向 Android 注册各种广播,Android 接收到广播会便会判断哪种广播需要哪种事件,然后向不同需要事件的应用程序注册事件,不同的广播可能处理不同的事件也可能处理相同的广播事件,这时就需要Android 系统为我们做筛选。
本软件就利用开机广播和短信接收广播来判断手机状态和控制手机。
3.3.4 GPS服务
对于GPS我想大家现在都很了解,至少不会陌生,一般情况下每个装载GPS的设备都会由3颗卫星进行定位,在需要时可将设备所在的位置信息发送到GPS上,例如返回的经纬度,有了这些位置信息我们便可进行需要的操作[10]。
在本应用中将会运用Android手机的GPS定位系统,为我们获取手机的当前位置,便于用户找回丢失的手机
3.3.5 私人数据的管理
当用户的手机丢失后恐怕最担心的就是自己私人信息的外露,出于此考虑,本软件将通过继承IntentService的类,对用户的通讯录、媒体图片进行备份并向安全手机发送,同时将原有数据删除,以防止不法分子的非法企图。
4 手机防盗应用方案的实施
按照手机防盗应用技术的设计理念,我将从UI入手,在做完界面的基础上组合、衔接并加入相应的功能,最后通过Service实现后台监听、储存、处理等功能。
在实现这些功能之前我们需要先搭建Android开发环境,其具体操作流程见附表二。
4.1 UI的实现
在Android系统中,UI的构建主要都由Activity类来完成。为了开发方便,Android又构造了多个继承Activity类的子类。其中在我们的软件里用到了ListActivity和PreferenceActivity两个子类和Activity本身。
4.1.1 Activity
要使用Activity以及其子类首先要知道Activity的生命周期,只有知道其生命周期的顺序才能控制好界面的显示。图4.1为Google官方给出的Activity生命周期流程图。
图 4.1 Activity生命周期
在本软件中有8个UI直接通过继承Activity类构成,他们的应用方法大同小异,我就拿其中最复杂的初始化界面来介绍。
初始化界面的整体设计流程图如图4.2所示。
图 4.2 初始化UI流程图
?.java文件:
首先新建一个继承Activity的类First
Public class First extends Activity{}
在此类里面对UI界面进行编辑
以下为关键代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 //覆写onCreate方法
public void onCreate(Bundle savedInstanceState) {
//绘制UI界面
setContentView(R.layout.first);
//用findViewById的方法声明并得到Button控件
Button bt_sure = (Button)findViewById(R.id.sure);
//用setOnClickListener方法绑定Button监听器,获取用户点击按钮事件
bt_sure.setOnClickListener(new OnClickListener() {}
//用if……else if……else if语句对用户设置信息进行判断
if(Str_password1.trim().equals("") || Str_password2.trim().equals("")) {
//用Toast.makeText()方法做出相应提示
Toast.makeText(First.this, "密码不能为空", Toast.LENGTH_LONG).show();
else if……
else{
//建立数据库编辑对象
Editor editor = sp.edit();
//储存安全密码到数据库
editor.putString("password", Str_password1);
//提交改动到数据库并保存
editormit();
//创建intent对象
Intent intent = new Intent();
//指明跳转Activity
intent.setClass(First.this, Main.class);
//开启要跳转的UI
First.this.startActivity(intent);
图 4.3 layout布局控件示意图
?layout.xml文件:
为Activity提供布局支持的layout文件是UI如何显示的控制中心,这个文件里的控件属性决定了控件的显示位置,图4.3是为First提供布局控件的layout的示意图,其主要代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 //第一行定义了布局文件所链接数据库的版本以及支持的语言,"utf-8"为中文。
// 采用LinearLayout绝对布局的orientation属性定为vertical既垂直布局,第//一行属性为Android固定格式,我们不用过多研究
android:orientation="vertical" >
//在布局文件中放进文本框并定义相关属性
//嵌套绝对布局的水平布局
//嵌套相对布局
?AndroidManifest.xml文件:
Android中设立了一个统一管理文件,这个文件可以理解为Android的一个注册表文件,在这个文件中,我们可以声明我们自己定义的权限。如果所用的组件需要权限但没有在这个文件注册,应用程序就会无法正常运行。任何一个Activity类都是需要注册的,所以本应用的 AndroidManifest.xml主要代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 //注册接受开机广播权限
//注册发送短信权限
//注册获取具体地址权限
//请求Activity显示
android:icon="@drawable/dun"
android:label="@string/fangdao" >
android:name=".Main"
android:label="@string/fangdao"
android:clearTaskOnLaunch="true" >
//通过intent-filter设置首显Activity
//注册广播接受类
//注册服务类
4.1.2 ListActivity
ListActivity 直接继承于Activity,是手机基本应用中最常用的一类应用程序。ListActivity用来在屏幕中显示一个列表,当点击其中的某一列时,可以触发一些操作。我们通过设置一个onListItemClick函数,来得到用户正选择了哪一列的信息,并做后续处理。使用了ListActivity类后,如果整个屏幕上只需显示一个列表,我们甚至可以把setContentView一行注释掉,不用定义列表的XML说明文件。因为ListActivity类已经默认绑定了一个ListView(列表视图)界面组件。图4.4就是一个典型的ListView示意图。
图 4.4 ListView示意图
在本软件中,UI主层和UI功能体验层的列表视图就是通过直接继承ListActivity这个类得到的。在继承ListActivity的类中要想显示列表内容就必须要调用setListAdapter(listAdapter)方法,在这个方法中需要传进一个listAdapter参数,这个Adapter通常我们叫做适配器,我们要显示出来的数据就储存在这个listAdapter当中。在list中的每一个数据都是一个HashMap。HashMap就是一种Map,在Map中数据都是以键值对的方式存在的,这样,我们的数据最终在List中的存储方式就是以键值对的形式存在的。我们只需要给Value对应的Key赋值就可以把我们要显示的数据装进List中了。下面以UI功能体验层为例根据图4.5的程序流程图分析下代码:
图 4.5 体验功能UI流程图
?Java文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 //首先我们的体验层要继承ListActivity
public class Tiyan extends ListActivity
//在这里设置各功能对应的数值
private static final int dingwei = 0; //定位手机
private static final int xiaohui = 1; //销毁数据
private static final int suoding = 2; //锁定手机
private static final int baojing = 3; //发报警音
private static final int huanka = 4; //换卡短信通知
//这里我们需要在layout文件中设置两个布局文件,一个用于主框架,另一个是为//list单独建立的,专门摆放list中的控件,下面这句代码就是主框架
setContentView(R.layout.tiyan);
//建立一个HashMap放进 ArrayList中
ArrayList> list
=new ArrayList>();
//分别生成对象,以map1为例,后面4组方法相同
HashMap map1 = new HashMap();
//向Map中对应位置装入数据,
map1.put("tiyan", "定位手机");
map1.put("jianjie", "获取手机当前位置,便于您找回");
map1.put("img", R.drawable.dingwei);
//将Map加入list,这样数据就存放在列表当中啦
list.add(map1);
//生成Adapter,并实现通过setListAdapter()方法实现list
SimpleAdapter listAdapter = new SimpleAdapter
(this,list,R.layout.tiyanlist,
new String[]{"tiyan","jianjie","img"},
new int[]{R.id.tyxx,R.id.tyjj,R.id.tytb});
setListAdapter(listAdapter);
//覆写onListItemClick()方法获得用户点击事件
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Intent intent = new Intent();
// intent.putExtra("textIntent","123");
//“防盗功能体验”界面
if(position == dingwei)
{
intent.setClass(Tiyan.this,Dingwei.class);
Tiyan.this.startActivity(intent);
}
else if()
……
}
图 4.6 ListActivity中layout框架
?layout.xml文件:
图4.6展示了在ListActivity中两个layout的布局框架,以下为代码分析:
?tiyan.xml文件:
在tiyan.xml文件中只有一个ListView控件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//这里注意ListView的id一定为list,这是android系统中默认的id,不能自拟。
android:id="@+id/android:list"
// scrollbars属性为选择滚动条方向,这里我们定位垂直方向。
android:scrollbars="vertical" />
?tiyanlist.xml文件:
在tiyanlist.xml文件中采用相对布局RelativeLayout,以方便控件的摆放
// ImageView为图片View,是用于添加图片的控件
//一下是两个文本信息,就是实际列表中要显示的值
4.1.3 PreferenceActivity
在Android中有一个Preference类,用于手机的属性设置。因此当我们在界面上做设置的时候自然就会想到Activity+Preference的组合,前者用于界面的构造,后者用于设置数据的存放。不过虽然做法没错,但是会比较繁琐,因为每个设置选项都要建立与其对应的Preference。当然Android的设计者也考虑到了这点,在系统中为我们提供了一个专门用于开发界面设置的类PreferenceActivity,这个类完美结合了Activity与Preference,很大程度的方便了我们的开发,因此我们的UI功能设置界面就是通过继承此类的类来实现。
继承PreferenceActivity的UI设置界面的java文件无需过多的编程代码,因为在PreferenceActivity上做的任何设置,系统都会自动以键值对的方式储存到数据库里,当我们需要这些数据的时候,便可以直接从数据库里调用。所以我们只需要在布局文件中按需求添加控件就可以了。
PreferenceActivity的布局文件有些特殊,需要在res文件夹下新建一个xml文件夹用于单独存放此类控件和布局属性,如图4.7所示。
图 4.7 Preference的布局文件
其shezhi.xml文件构架如图4.8所示。
图 4.8 shezhi.xml文件构架
控件属性在本软件中的应用如图4.9所示。
图 4.9 shezhi.xml文件属性构架
其代码就是对属性进行相应配置即可如android:password="true"等,这里就不做详细介绍了,具体代码请看附录二。
4.1.4 Dialog
Dialog是android开发过程中最常用到的组件之一,它包括以下几种类型:
1.警告对话框:Alertialog
2.进度对话框:ProgressDialog
3.日期选择对话框:DatePickerDialog
4.时间选择对话框:TimePickerDialog
5.自定义对话框:从Dialog继承
Dialog的创建方式有两种:
一是直接new一个Dialog对象,然后调用Dialog对象的show和dismiss方法来控制对话框的显示和隐藏。
二是在Activity的onCreateDialog(int id)方法中创建Dialog对象并返回,然后调用Activty的showDialog(int id)和dismissDialog(int id)来显示和隐藏对话框。
区别在于通过第二种方式创建的对话框会继承Activity的属性,比如获得Activity的menu事件等。
本软件就采用第二种方法用于显示弹出的对话框。其程序流程图如图4.10所示。
图 4.10 Dialog流程图
?java文件关键代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 //首先先创建一个Dialog函数
private void putPWDialog() {
//渲染布局文件
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.putpwdialog, null);
//生成Dialog对象并进行设置
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("输入密码");
//显示Dialog界面
builder.setView(view);
showputPWDialog = builder.create();
showputPWDialog.show();
//监听确定按钮
btn_sure.setOnClickListener(new OnClickListener() {
//信息核对提示
if(password.trim().equals("")) {
else if(password.trim().equals(savedPassword)) {
else{}
//监听退出按钮
btn_exit.setOnClickListener(new OnClickListener() {
//完全退出程序
public void onClick(View v) {
MyApplication.getInstance().exit();
}
经过大量的调整、核对以及调试,我们的UI界面就这样完成啦。到此为止把我们的软件安装到手机上就可以进行所有界面的切换了。
4.2 由Sever支持的Function实现
有了完整的UI,我们就可以在Function里实现这些UI对应的功能。对于任何一个软件来说,无论它有什么样的UI,人们最终想要获得的还是软件的功能。所以,只有Function的完美实现才能体现出一个软件的真正价值。
4.2.1 广播机制服务
之前已经介绍了Android系统中广播机制的概念,这里就主要说明在本软件中所用到的3种广播——开机完成广播、服务状态广播和短信接收广播。
开机完成广播和服务状态广播用于监测SIM卡的状态改变。当用户开机完成时,系统就会向接收开机完成广播的应用软件发送开机完成广播,告诉他们已完成开机动作,此时软件就可以在接收此指令后做出自己需要的动作,例如开机运行的软件就都需要接收开机完成广播。服务状态广播也是同样的原理,当手机检测到信号后就会由系统向所有应用发送服务状态改变的广播。
短信接收广播是当手机接收到短信时Android系统向应用程序发送的一种广播。手机系统中自带的有些功能都要通过这种广播来完成动作。例如手机收到短信时会产生音乐和振动等状态,这就是由短息模块在接收到系统短信接收广播后作出的动作。
为了接收来自系统的广播,Android为开发者提供了一个专门用于接收广播的类既BroadcastReceiver类,本软件就通过继承此类实现接收所有广播。在Android中光有接收的类还不行,要想让系统把广播发送到你的应用程序还必须在AndroidManifest.xml文件中进行权限注册,让系统知道你需要接收广播并给你开放ROOT允许你使用才行。下面代码为本应用所有的权限注册代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在本软件中远程控制手机就是通过此短信广播接收机制实现的。当系统收到短信后会向需要接收广播的应用发送短信广播,本应用接收广播后就可根据短信内容做出相应的动作了。其服务程序流程图如图4.11所示。
图 4.11 SMS服务流程图
短信接收后台服务关键代码解析如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 //创建SMSReceivedBroadcastReceiver类继承BroadcastReceiver类实现接收短信广播
public class SMSReceivedBroadcastReceiver extends BroadcastReceiver {
//覆写父类onReceive方法执行动作
public void onReceive(Context context, Intent intent) {
// 检测防盗保护是否开启
if(isprotect) {
//通过msgs[i].getDisplayOriginatingAddress()方法得到来源短信电话号码
//对比是否为安全手机号
if(oriAddress.trim().equals("+86" + safenumber)){}
else if(oriAddress.trim().equals("12520" + safenumber)){}
else if(oriAddress.trim().equals(safenumber)) {}
// 1.执行GPS定位
if(body.contains("dingwei#" + password)) {}
// 2.执行锁定手机
else if(body.contains("suoding#" + password)){}
// 3.执行发报警音
else if(body.contains("baojing#" + password)){}
// 4.执行销毁数据
else if(body.contains("xiaohui#" + password)){}
}
4.2.2 换卡短信通知
本应用在开机完成后首先接收系统发出的开机完成广播,这时软件就会在后台开始检测SIM卡的IMSI码信息,如果此信息与原保存的IMSI码不一致,则说明手机处于非安全状态。待手机检测到信号,可执行移动服务的时候,服务状态广播就会向手机所有应用发送此广播。当本应用接收到此广播后就会立即向安全手机号发送SIM卡被更换的报告。其服务效果如图4.12所示。
图 4.12 开机检测SIM卡信息流程图
开机检测SIM卡程序主要代码分析如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 //创建一个用于开机接收广播的类BootCompleteReceiver
public class BootCompleteReceiver extends BroadcastReceiver {
//覆写父类中的onReceive执行动作
public void onReceive(Context context, Intent intent) {
//判断是否开启防盗保护和换卡通知
if(isprotect && issendID) {
//通过getSubscriberId()方法提取SIM卡IMSI号
String IMSI = tm.getSubscriberId();
//判断是否与安全IMSI号相等
if(IMSI.trim().equals(safeIMSI)) {
return;
}
//不等则后台向安全手机号发送短信
else {
SmsManager manager = SmsManager.getDefault();
List message = manager.divideMessage("手机IMSI码为:" + safeIMSI + " 的手机,SIM已被更换,更换的IMSI码为:" + IMSI);
for(String msg : message) {
manager.sendTextMessage(safenumber, null, msg, null, null);
4.2.3 定位手机
Android系统可通过手机的GPS模块为我们提供当前手机的位置信息既经纬度。然后我们再通过向服务器发送地址请求的方式得到手机的具体位置既街道等。其具体实现流程图如图4.13所示。
图 4.13 GPS定位流程图
GPS定位的主要代码分析如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 //建立一个GPS类继承Service
public class GPS extends Service{
//创建一个getGPS方法用于获取GPS地址
public void getGPS(Context context){
//得到LocationManager对象
LocationManager locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
//获取指定时间指定偏移距离地址信息
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new TestLocationListener());
}
//实现LocationListener接口
public class TestLocationListener implements LocationListener{
//当用户位置发生改变时获取经纬度
public void onLocationChanged(Location location) {}
//指定请求服务器 域名
String url = "maps.googleapis/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false";
//创建一个HttpClient对象
HttpClient httpClient = new DefaultHttpClient();
//向指定的URL发送Http请求
HttpResponse response = httpClient.execute(new HttpGet(url));
//取得服务器返回的响应
HttpEntity entity = response.getEntity();
//生成Gson对象
Gson gson = new Gson();
//解析Gson数据并存入testResult
testResult = gson.fromJson(responseData, TestResult.class);
有了提供具体位置的GPS服务类,我们只需将信息通过SMS发送到指定安全号码即可远程获得手机的具体位置了。
4.2.4 数据销毁
为了避免隐私泄露,我们需要创建一个专门的类用于处理我们的用户信息,此类应具有备份和删除两个功能。对于用户的隐私文件我们把焦点主要放在联系人和媒体上。因此,我们需要连接并提取联系人和媒体的资料,并拥有删除这些文件的权限方可达到目的。其实现流程图为图4.14所示。
图 4.14 销毁数据流程图
其主要代码分析如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 //创建创建TaskService类继承IntentService类
public class TaskService extends IntentService {
//覆写父类onHandleIntent方法
protected void onHandleIntent(Intent intent) {
//通过intent.getIntExtra方法提取选择功能
int code = intent.getIntExtra(GuardSettings.EXTRA_TASKCODE, -1);
switch(code){
case GuardSettings.TASKCODE_BACKCONTACTS:
Log.i("guard", "备份联系人");
backContacts();
break;
case GuardSettings.TASKCODE_DELETECONTACTS:
Log.i("guard", "删除联系人");
deleteContacts();
break;
case GuardSettings.TASKCODE_DELETEMEDIAS:
Log.i("guard", "删除媒体信息");
deleteMedia_Images();
break;
}
4.2.5 锁定手机
当收到锁定手机的指令后,要求手机立刻进入锁屏状态,只能在屏幕上输入安全密码,密码验证通过后手机会恢复正常,要是密码错误则会禁止用户任何操作,直到密码输入正确为止才能使用。其实现效果如图4.15所示。
图 4.15 锁屏流程图
根据程序流程,所以用户一定要在安装完本应用后实现一次锁屏获得ROOT权限后方可远程控制锁屏功能实现。以下为功能实现分析:
?DevicePolicyManager:顾名思义,这个类的作用是管理设备。通过这个类,我们可以实现屏幕锁定、亮度调节甚至是恢复出厂设置等功能。
?DeviceAdminReceiver:这个类的父类是BroadcastReceiver,通过其OnReceive方法可以根据不同的Action执行不同的动作。
, 这个程序的开发过程大致如下:
要想使用DevicePolicyManager中的方法,首先要定义一个Component。然后通过管理这个组件来启动一个DeviceAdminReceiver。
注册一个广播,用于监听权限的变化,代码在AndroidMenifest.xml文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 android:name=".LockScreenAdmin"
android:label="@string/app_name"
android:description="@string/app_name"
//表示此功能所需的权限
android:permission="android.permission.BIND_DEVICE_ADMIN">
//表示这个动作的跳转界面
??????? android:resource="@xml/lock_screen_admin" />
???
其中, android:resource="@xml/lock_screen_admin"所指向的内容如下:
1
2
3
4
5
6 ? xmlns:android="schemas.android/apk/res/android">
???
???????
???
实现一个继承自DeviceAdminReceiver的类,实现必须的方法。这个类基本不用写代码,在此略过不表。
这段代码用来在第一次运行的时候激活component,只要激活一次之后,这个component就会一直是激活的。使用startActivityForResult()可以在onResult方法中调用lockNow()来锁屏,当不是第一次运行的时候,直接调用lockNow()锁屏。
1
2
3
4
5
6
7
8
9
10
11
12 if (mDevicepolicymanager.isAdminActive(mComponentname)) {
??????????? mDevicepolicymanager.lockNow();
??????????? finish();
??????? } else {// 第一次运行程序
??????????? Intent intent = new Intent(
??????????????????? DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
??????????? intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
??????????????????? mComponentname);
??????????? intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
??????????????????? "One key lock screen need to active");
??????????? startActivityForResult(intent, RESULT_ENABLE);
??????? }
4.2.6 发报警音
发报警音的功能实现比较简单,只需要在收到指令后在后台开启影音即可,主要代码如下所示:
1
2 mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
4.2.7 数据库存储应用
由于本程序正常工作时运行在后台,所以要运用数据库存放数据。这里数据库的运用在每个单元功能内都必不可少,是否开启防盗功能、是否是第一次启动应用程序、安全手机号、安全密码等数据都交由数据库保存。以安全密码为例在程序中运用代码如下所示:
1
2
3
4
5
6
7
8
9
10
11 //连接数据库生成称对象
SharedPreference sp = context.getSharedPreferences("j.fangdao_preferences", Context.MODE_WORLD_WRITEABLE);
//提取安全密码运用
String safenumber = sp.getString("safenumber", "");
//生成Editor对象
Editor editor = sp.edit();
//修改更新数据
editor.putString("Ssafenumber", Tsafenumber);
//提交数据并保存
editormit();
5 手机防盗应用测试
同时开启两台模拟器,两台的电话号码分别为和。在上安装本应用软件,另一台用于发送指令。
5.1 防盗应用初始化
安装完成后初始化手机防盗应用,设置密码为123456,安全手机号为。如图5.1所示。
图 5.1 初始化设置
在设置界面里开启所有功能。
关闭此防盗应用,退回到手机主界面。
5.2 手机定位功能测试
用向发送指令:123456#dingwei,(因为是模拟器,所以需要预先在DDMS里给手机设定GPS地址。)等待片刻后即收到返回的地址信息如图5.2所示。
图 5.2 定位功能
由于是模拟器演示,模拟器不支持中文,所以现在返回的是一些乱码,到真机上就能看懂了。
5.3 换卡短信通知功能测试
接下来我们进入DDMS,在Devices窗口里选中emulator-5554,然后在File Explorer窗口中进入data/data/j.fangdao文件夹,如图5.3所示。
图 5.3 换卡通知date
在shared_prefs文件夹中找到j.fangdao_preferences.xml文件并将其倒出。如图5.4所示。
图 5.4 数据库位置
这个文件就是数据库文件,将其SIM卡的IMSI号码更改,然后倒入源地址,这样就能模拟换卡的状态了。数据库IMSI码更换前后如图5.5和图5.6所示。
图 5.5 数据库IMSI码更换前
图 5.6 数据库IMSI码更换后
关闭模拟器然后再打开,开机完成后收到更换SIM卡信息如图所示。
5.4 锁屏功能测试
用手机响手机发送指令:123456#suoding
收到指令的手机手机立即进入锁屏状态如图5.7所示。
图 5.7 锁屏功能
5.5 销毁数据
由于模拟器没有SD卡,所以本功能只能在真机上测试,其测试方法同样是靠短信指令实现,测试后查看SD卡数据及手机通讯录和媒体数据已全部清空。既销毁数据功能实现。
5.6发报警音
由于模拟器也无法播放媒体,所以也只能真机测试,由于本功能属于后台运行,真机测试时,当收到指令立即以最大音量报警,既发报警音功能实现。
6 手机防盗应用说明
首先开启防盗应用软件进入初始化界面,在第一个文本框输入安全密码,第二个文本框输入确认密码,两次密码输入必须符合提示要求,否则将不被软件认可。在下面的文本框输入安全[网学网用户上传],此号码建议输入亲友电话,在输入非法号码时,软件将给出相应提示并允许用户重新输入。
?手机SIM卡被更换:您向被盗手机发送了锁定手机指令以上两种情况,手机防盗将为您锁定被盗手机,防止别人使用您的手机或查看隐私信息。
?手机定位:手机被盗后,可以用任意手机发送定位手机指令到被盗手机,获取手机当前位置,帮您找回手机。定位手机成功后,将会发送短信告知您手机的位置。
*定位手机指令:dingwei#防盗密码
?销毁数据:手机被盗后,用安全手机号发送销毁指令到被盗手机,可彻底销毁手机数据,保护隐私不被泄露。销毁的数据包括:通讯录、短信、照片及SD卡的其他数据。特别提醒:销毁数据指令必须使用安全手机号发送。
*销毁数据指令:xiaohui#防盗密码
?锁定手机:当手机收到锁定手机指令后会立即锁屏,只有输入正确的安全防盗密码才可解锁手机 。
*锁定手机指令:suoding#防盗密码
?发报警音:发觉手机被盗后,可用任意手机发送报警指令到被盗手机。这时被盗手机将发出最大音量的报警声(即使是静音模式),帮助您快速找到手机。
*发报警音指令:baojing#防盗密码
用户可在设置界面对初始化设置的安全密码和安全手机号进行修改,并可设置防盗功能开关、换卡通知开关以及换卡锁定开关。
结论
在这个高度信息化的时代,手机的丢失总会给人带来很多烦恼,但最让人烦心的是手机中存储的多年好友通讯录、记载着岁月的照片、视频等私人数据都一并丢失。本文所设计的软件就是专门为解决此问题而设计的。
本文结合用户手机丢失导致私人信息不安全的问题,总结手机丢失给用户带来的后果,然后根据需求设计软件。本软件基于Android系统平台进行设计,所以文章从软件的UI入手,对比并采用市场上最受用户喜欢的列表式界面设计,应用继承ListActivity的类完美实现。在设置功能按钮的设置界面采用Android系统级UI专用设置类PreferenceActivity参与设计,并以最方便的排版方式实现设置层UI。做好显示后应用Intent传递各UI间的数据,并在关闭软件后将必要的数据存储在SharedPreferences数据库中。在完成整个UI设计后文章逐个介绍每个功能的实现方法及过程。其中运用GPS技术定位手机,并可通过Android系统广播机制,控制手机向指定手机发送当前手机具体位置。要想通过短信控制被盗手机,就要知道被盗手机的[网学网用户上传],为此,文章从[网学网用户上传]来源入手分析,总结得出要想知道当前手机号,必须要获得此手机SIM卡的IMSI码来确定唯一的SIM卡,拥有IMSI码号后便可到移动公司查到当前SIM卡的手机号进而才可实现功能。由问题又引出亲的问题,接下来就要解决如何获取SIM卡IMSI号的问题,这里本章介绍了如何运用Android广播机制中的开机广播和信号广播以及短信广播来监听手机SIM卡状态。在软件检测到SIM卡被更换时,会立即将当前SIM卡信息传递到SMS机制并向指定手机发送指令要求信息。接下来本章具体讲述了在能远程向被盗手机发送指令的情况下如何实现锁屏、销毁隐私数据以及报警等其他防盗功能。
所有功能的实现都在后台完成,这样才能在让非法分子在毫无察觉的情况下绳之以法。本文具体介绍了后台服务的Service,所用到的具体数据都来源于Service服务。GPS的定位、用户隐私数据的备份发送与销毁等功能的实现都是因为拥有强大的后台Service支持才得以实现。
经过大量实验调试,最终本软件实现了所有防盗功能。当安有此防盗软件手机丢失时,后台工作的软件会自动检测到不安全状态,待安全手机号收到目标手机当前手机号后便可通过防盗指令控制被盗手机锁屏并以最大音量发报警音,在不法分子还没来得反应的时候,公安人员已经按照软件所提供的GPS定位地址将其制服并拿回属于用户的手机。如果不法分子为了消赃毁坏了手机,那我想在手机被盗的第一时刻用户就已经把自己的重要信息备份出来了,再无忧患所言。
致谢
经过几个月的努力,本人的毕业设计“基于Android系统的手机防盗应用”以完美完成。作为一个本科生的毕业设计,由于经验的匮乏,难免有许多考虑不周全的地方,如果没有导师的督促指导,以及一起工作的同学们的支持,想要完成这个设计是难以想象的。
首先要感谢的是我的导师刘军华老师,在我当初想要以Android系统应用作为我毕设题目的时候,给了我很大的鼓励与支持。本来在做毕设的同学,毕设题目是的老师指定好的,学生需在所有题目中选择一个作为自己的毕设来做。我学的专业是电子信息工程,所学的知识以硬件为主,因此所有的题目都是以硬件为主的,特别是我导师刘军华的题目,基本都是以ARM研究为主的。但是我对Android系统这个纯软件方向比较感兴趣,就想做个Android的应用作为自己的毕设,所以很是为难。但当我和刘老师说了我的想法后,他没有反对,反而非常支持,并想给我介绍到一家做Android的公司去学习并完成毕设。而后又帮我设定并确定毕设要完成的任务,如我愿的以“基于Android系统的手机防盗应用”项目做为了自己的毕业设计。也只有老师这样的抉择才能实现我现在的毕业设计。在这里对刘老师深表感谢!
对于Android系统我属于白手起家,甚至连Java语言都不是很扎实,所以一上来就像做应用是根本不可能的事。我的同学对Android有一些了解,知道我要做Android系统应用的毕设后主动帮我找资料,介绍Android的个大论坛,以及其编译环境等,给初学者的我指明了学习的方向,少走了很多弯路,非常感谢你们!
关于我对Android系统学习影响最大的就是mars老师了,mars老师是Android教学视频的老师,虽然他不认识我,但我几乎说有的Android系统知识都来源于mars老师的课程。mars老师不仅Android系统讲得好,而且还为我这样的初学者专门做了一系列Java4Android的视频很好的弥补了我的Java基础不足的缺陷。这里郑重感谢网络教师mars老师,感谢您的教导,祝您的教育事业越办越好!
还不能忘了感谢我们最常用的百度和Google公司,他们的文库为我提供了巨大地资料,决绝了我很多问题。还有QQ群Android联盟里的同志们,有了你们的帮助才使我少走弯路,在我不理解的时候你们耐心讲解,虽然我们并不知道彼此的容颜,但我却深知你们那份乐于助人的心。真心的感谢您们,祝你们工作顺利!
感谢我的父母,在我在家做毕设的时候,他们耐心的为我做饭,尽最大努力帮我排除一切影响因素,儿子在这里谢谢您们!祝您们身体健康!
一路走来,要感谢的人太多了,是你们的帮助才有我现在的成就,谢谢你们!
参考文献
1张浩,基于Android平台手机防盗追踪功能的实现[J].昆明理工大学信息工程与 自动化,2011年8月17日.
2盖锁林,王世江.Google Android开发入门指南[M].第二版.人民邮电出版社,2011年2月.
3吴亚峰,苏亚光. Google Android应用案例开发大全[M].人民邮电出版社,2011年9月1日
4胡辛征,高洪霞.21天学通Java[M].第二版.电子工业出版社,2011年7月.
5E2EColud工作室.深入浅出Google Android[M].人民邮电出版社,2009.
6林城.Android2.3应用开发实战[M].机械工业出版社,2011年6月1日.
7李刚.疯狂Android讲义[M].电子工业出版社,2011年6月22日.
8吴亚峰,索依娜,百纳科技.Android核心技术与实例详解[M].电子工业出版社,2010年10月1日.
9余志龙,王世江.Google Android SDK开发范例大全[M].人民邮电出版社,2010年6月1日.
10靳岩,姚尚朗.Android开发入门与实战[M].人民邮电出版社,2009年7月1日.
11Mars.Mars的个人论坛[EB/OL]. mars-droid/bbs/forum.php, 2011年9月10日/2012年3月5日.
12Mars.Android视频教程[CD].mars视频,2010年11月/2012年3月.
13Mars.Java4Android视频教程[CD].mars视频,2011年11月/2012年3月.
14Sunchaoenter.Android之PreferenceActivity[J/OL].CSDN,2012年1月16日/2012年4月9日.
15AndLi.ListView and CheckBox[J/OL].ITCYC,2011年9月30日/2012年4月20日.
16JaCman.listview加在性能优化ViewHolder[J/OL].CSDN,2011年12月20日/2012年5月3日.
17allin.android.android ListView详解[J/OL].android diordna,2011年12月19日/2012年5月15日.
18Sayed Hashimi.Pro Android 3[M].Apress,2011.
19Donn Felker.Android Application Development for Dummies[M].HUNGRY MINDS,2010.11.22.
20Mark Murphy.Beginning Android 3[M].Apress,2011.
21Ed Burnett,Susannah Davidson Pfalzer. Hello, Android: Introducing Google's Mobile Development Platform[M]. Pragmatic Bookshelf,2011.
附录一
图片:
附录二
一 相关下载
(1) java JDK下载:
进入该网页: java.sun/javase/downloads/index.jsp
如下图:
选择 Download JDK 只下载JDK,无需下载jre.
(2)eclipse下载
进入该网页: eclipse.org/downloads/如下图:
我们选择第一个(即eclipse IDE for java EE Developers)
(3)下载Android SDK
说明: Android SDK两种下载版本,一种是包含具体版本的SDK的,一种是只有升级工具,而不包含具体的SDK版本,后一种大概20多M,前一种70多M。
?? (1)安装jdk 6u19:安装完成即可,无需配置环境变量
?? (2)解压eclipse:eclipse无需安装,解压后,直接打开就行
?? (3)解压android sdk:这个也无需安装,解压后供后面使用
?? (4)最终有三个文件夹,如下图:
???
三 Eclipse配置
1 安装android 开发插件
(1)打开Eclipse, 在菜单栏上选择 help->Install New SoftWare 出现如下界面:
点击 Add按钮,出现如下界面
输入网址: https://dl-ssl.google/android/eclipse/?????
名称: Android (这里可以自定义)
点击OK,将出现如下界面
点击 Next按钮 ,出现如下界面:
点击Next按钮,出现如下界面:
选择 I accept the terms of the license agreements?点击Next,进入安装插件界面
安装完成后,出现如下界面
点击Yes按钮,重启Eclipse
2 配置android sdk
(1)点击菜单window->preferences,进入如下界面
选择你的android SDK解压后的目录,选错了就会报错,这个是升级工具,目前还没有一个版本的SDK
(2)升级SDK版本,选择菜单 window->Android sdk and avd manager 出现如下界面
??????
选择update all按钮,出现如下界面
选择左边的某一项,点击accept表示安装,点击reject表示不安装,我这里只选了SDK 2.1 和samples for api 7 , 自己可以任意自定义,确定后,选择install按钮,进入安装界面如下:
安装完成如下:
(3)新建AVD(android vitural device)??? 和上面一样,进入android sdk and avd manager,选中Vitural Devices 在点击New按钮
点击New按钮后,进入如下界面:
名称可以随便取,target选择你需要的SDK版本,SD卡大小自定义,点击 Create AVD,得到如下结果
如上显示创建AVD完毕
附录三
源代码:
src文件java代码:
1.Baojing.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package j.fangdao;
import android.app.Activity;
import android.os.Bundle;
public class Baojing extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
setContentView(R.layout.baojing);
}
}
2.BootCompleteReceiver.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 package j.fangdao;
import java.util.List;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
public class BootCompleteReceiver extends BroadcastReceiver {
SharedPreferences sp;
TelephonyManager tm;
@Override
public void onReceive(Context context, Intent intent) {
sp = context.getSharedPreferences("j.fangdao_preferences", Context.MODE_WORLD_WRITEABLE);
tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
boolean isprotect = sp.getBoolean("protect", false);
boolean issendID = sp.getBoolean("sendID", false);
System.out.println("开机");
System.out.println("isprotect------->" + isprotect);
System.out.println("issendID------->" + issendID);
if(isprotect && issendID) {
String safeIMSI = sp.getString("IMSI", "");
String safenumber = sp.getString("safenumber", "");
//IMSI
String IMSI = tm.getSubscriberId();
System.out.println("subscriberId-------->"+IMSI);
if(IMSI.trim().equals(safeIMSI)) {
return;
}
else {
//SmsManager
SmsManager manager = SmsManager.getDefault();
List message = manager.divideMessage("手机IMSI码为:" + safeIMSI + " 的手机,SIM已被更换,更换的IMSI码为:" + IMSI);
for(String msg : message) {
manager.sendTextMessage(safenumber, null, msg, null, null);
System.out.println("已发送");
}
}
}
else {
return;
}
}
}
3.Chakan.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package j.fangdao;
import android.app.Activity;
import android.os.Bundle;
public class Chakan extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
setContentView(R.layout.chakan);
}
}
4.Dingwei.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package j.fangdao;
import android.app.Activity;
import android.os.Bundle;
public class Dingwei extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
setContentView(R.layout.dingwei);
}
}
5.First.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 package j.fangdao;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class First extends Activity{
boolean isFirst;
SharedPreferences sp;
TelephonyManager tm;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
sp = this.getSharedPreferences("j.fangdao_preferences", MODE_WORLD_READABLE);
//IMSI
tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
final String IMSI = tm.getSubscriberId();
final EditText et_password1 = (EditText)findViewById(R.id.password1);
final EditText et_password2 = (EditText)findViewById(R.id.password2);
final EditText et_safenumber = (EditText)findViewById(R.id.safenumber);
Button bt_sure = (Button)findViewById(R.id.sure);
Button bt_exit = (Button)findViewById(R.id.exit);
bt_sure.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String Str_password1 = et_password1.getText().toString();
String Str_password2 = et_password2.getText().toString();
String Str_safenumber = et_safenumber.getText().toString();
if(Str_password1.trim().equals("") || Str_password2.trim().equals("")) {
Toast.makeText(First.this, "密码不能为空", Toast.LENGTH_LONG).show();
return;
}
else if(Str_password1.trim().length() < 6 || Str_password1.trim().length() > 12){
Toast.makeText(First.this, "请输入6-12位数字或字母的密码", Toast.LENGTH_LONG).show();
return;
}
else if(!Str_password1.trim().equals(Str_password2.trim())){
Toast.makeText(First.this, "密码两次输入不一致,请重新输入", Toast.LENGTH_LONG).show();
return;
}
else if(Str_safenumber.trim().equals("") ){
Toast.makeText(First.this, "[网学网用户上传]不能为空", Toast.LENGTH_LONG).show();
return;
}
else if(Str_safenumber.trim().length() != 11 ){
Toast.makeText(First.this, "[网学网用户上传]错误", Toast.LENGTH_LONG).show();
return;
}
else{
// 建立数据库编辑对象
Editor editor = sp.edit();
// 储存当前手机IMSI到数据库
editor.putString("IMSI", IMSI);
// 储存密码到数据库
editor.putString("password", Str_password1);
// 储存安全手机号到数据库
editor.putString("safenumber", Str_safenumber);
// 改first值为false,再次打开应用时不进入此Activity
editor.putBoolean("first", false);
// 提交改动到数据库并保存
editormit();
// 创建intent对象
Intent intent = new Intent();
// 指明跳转Activity
intent.setClass(First.this, Main.class);
First.this.startActivity(intent);
}
}
});
bt_exit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// 调用exit方法完全退出
MyApplication.getInstance().exit();
}
});
}
}
6.GPS.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 package j.fangdao;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import junit.framework.TestResult;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.telephony.SmsManager;
import com.google.gson.Gson;
public class GPS extends Service{
TestResult testResult;
String Gsafenumber;
SharedPreferences sp;
int a = 0;
public void getGPS(Context context){
a = 1;
sp = context.getSharedPreferences("j.fangdao_preferences", Context.MODE_WORLD_WRITEABLE);
Gsafenumber = sp.getString("Ssafenumber", "");
System.out.println("----------->1");
LocationManager locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
System.out.println("----------->2");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new TestLocationListener());
System.out.println("----------->3");
}
public class TestLocationListener implements LocationListener{
@Override
public void onLocationChanged(Location location) {
System.out.println("<<<1");
// TODO Auto-generated method stub
System.out.println(location.getLongitude());
System.out.println(location.getLatitude());
if(a == 1){
a = 0;
String url = "maps.googleapis/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false";
System.out.println("<<<2");
//创建一个HttpClient对象
HttpClient httpClient = new DefaultHttpClient();
System.out.println("<<<3");
String responseData = "";
System.out.println("<<<4");
try{
//向指定的URL发送Http请求
HttpResponse response = httpClient.execute(new HttpGet(url));
System.out.println("<<<5");
//取得服务器返回的响应
HttpEntity entity = response.getEntity();
System.out.println("<<<6");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
System.out.println("<<<7");
String line = "";
System.out.println("<<<8");
while((line = bufferedReader.readLine()) != null){
responseData = responseData + line;
}
System.out.println("<<<9");
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("<<<10");
Gson gson = new Gson();
System.out.println("<<<11");
testResult = gson.fromJson(responseData, TestResult.class);
System.out.println("<<<12");
System.out.println(testResult);
SmsManager manager = SmsManager.getDefault();
if(testResult == null){
List message = manager.divideMessage("目标手机当前位置为:经度:" + location.getLongitude() + "纬度:" + location.getLatitude() + "您可根据此经纬度到网上查到真是地址" );
System.out.println("已发送");
for(String msg : message) {
manager.sendTextMessage(Gsafenumber, null, msg, null, null);
System.out.println("<<<13");
}
}
else{
List message = manager.divideMessage("目标手机当前位置为:" + testResult );
System.out.println("已发送");
for(String msg : message) {
manager.sendTextMessage(Gsafenumber, null, msg, null, null);
System.out.println("<<<13");
}
}
}
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
7.Huanka.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package j.fangdao;
import android.app.Activity;
import android.os.Bundle;
public class Huanka extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
setContentView(R.layout.huanka);
}
}
8.Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 package j.fangdao;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Intent;
import android.content.SharedPreferences;
impor, t android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class Main extends ListActivity {
boolean isFirst;
boolean isDialog;
SharedPreferences sp;
AlertDialog showputPWDialog;
private static final int tiyan = 0; //防盗功能体验
private static final int chakan = 1; //防盗指令查看
private static final int shezhi = 2; //防盗信息设置
/** Called when the activity is first created. */
public void getMaxVolume(){
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 添加该Activity到MyApplication对象实例容器中
MyApplication.getInstance().addActivity(this);
sp = this.getSharedPreferences("j.fangdao_preferences", MODE_WORLD_READABLE);
isFirst = sp.getBoolean("first", true);
isDialog = sp.getBoolean("Dialog", false);
if(isFirst){
Intent intent = new Intent();
intent.setClass(Main.this, First.class);
Main.this.startActivity(intent);
}
else{
/////////////////测试区/////////////
// Editor editor = sp.edit();
// editor.putBoolean("first", true);
// editormit();
////////////////////////////////////
if(isDialog){
putPWDialog();
}
else{
init();
Editor editor = sp.edit();
editor.putBoolean("Dialog", true);
editormit();
}
setContentView(R.layout.main);
}
}
private void init() {
/* Button bt_exit1 = (Button)findViewById(R.id.exit2);
bt_exit1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// 调用exit方法完全退出
MyApplication.getInstance().exit();
}
});*/
ArrayList> list = new ArrayList>();
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
HashMap map3 = new HashMap();
map1.put("fangdao", "防盗功能体验");
map1.put("jianjie", "了解手机防盗提供哪些功能");
map1.put("img", R.drawable.tiyan);
map1.put("jiantou", R.drawable.jiantou);
map2.put("fangdao", "防盗指令查看");
map2.put("jianjie", "手机丢失后如何遥控操作");
map2.put("img", R.drawable.chakan);
map2.put("jiantou", R.drawable.jiantou);
map3.put("fangdao", "防盗信息设置");
map3.put("jianjie", "修改防盗密码、安全手机号等");
map3.put("img", R.drawable.shezhi);
map3.put("jiantou", R.drawable.jiantou);
list.add(map1);
list.add(map2);
list.add(map3);
SimpleAdapter listAdapter = new SimpleAdapter
(this,list,R.layout.mainlist,
new String[]{"fangdao","jianjie","img","jiantou"},
new int[]{R.id.fdxx,R.id.fdjj,R.id.fdtb,R.id.fdjt});
setListAdapter(listAdapter);
}
private void putPWDialog() {
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.putpwdialog, null);
final EditText et_password = (EditText) view.findViewById(R.id.password3);
Button btn_sure = (Button) view.findViewById(R.id.sure1);
Button btn_exit = (Button) view.findViewById(R.id.exit1);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("输入密码");
builder.setView(view);
showputPWDialog = builder.create();
showputPWDialog.show();
btn_sure.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String password = et_password.getText().toString();
String savedPassword = sp.getString("password", "");
上一篇:基于Android的移动公交查询系统设计与实现
下一篇:一个电子病例系统数据库通讯中间件的设计模型