一. 绑定SIM卡

获取SIM卡信息并保存起来

找到控件、处理click事件、选中则绑定

layout里改一下id,具体点,是绑定sim

<com.rjl.mobilephonemanager.ui.SettingItemandroid:id="@+id/settingitem_bindsim"android:layout_width="fill_parent"android:layout_height="wrap_content"rjl:itemtitle="点击绑定sim卡"rjl:desc_checkbox_on="已经绑定"rjl:desc_checkbox_off="尚未绑定"/>

这里需要一个checkbox,我们最好在settingItem里暴露一个方法出来,自己调用checkbox,外面只需要调用这个settingitem组合控件就能调用到checkbox了

init里初始化,然后暴露一个方法,返回是否勾选的状态isCheck()

private void init() {// TODO Auto-generated method stub/*View view= View.inflate(getContext(), R.layout.setting_item, null);    //将控件的view加载到这个view上this.addView(view);*/View v= View.inflate(getContext(), R.layout.setting_item, this);tv_setting_title = (TextView) v.findViewById(R.id.tv_setting_title);tv_setting_description = (TextView) v.findViewById(R.id.tv_setting_description);cb_settingitem = (CheckBox) v.findViewById(R.id.cb_settingitem);}
public boolean getChecked(){return cb_settingitem.isChecked();}

OK,然后在activity里调用

看一下逻辑,判断是否绑定,然后根据用户的点击去更改他的状态。

用户要点击,也就是说原来isChecked为true,点击后变为false,原来是false,点击后变为true,这就需要在settingItem里暴露一个方法,能够接受用户在activity2的点击,然后去改变boolean

同时点击后显示的text也要改变

settingitem_bindsim.setOnClickListener(new MySettingItemListener());     }class MySettingItemListener implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(settingitem_bindsim.getChecked()){//check为true,则要设为false,这个setcheck也要去settingItem里暴露settingitem_bindsim.setCheck(false);settingitem_bindsim.setdescriptionoff();              }else{settingitem_bindsim.setCheck(true);settingitem_bindsim.setdescriptionon();}}      }

settingItem里的方法接收状态的改变

public void setCheck(boolean checked){cb_settingitem.setChecked(checked);}

这里也可以更近一步,随着状态的改变,显示自动变了,而不是在代码里手动加上description,故而在settingItem的接收里面添加上就好,方便复用

public void setCheck(boolean checked){cb_settingitem.setChecked(checked);if(checked){setdescriptionon();}else{setdescriptionoff();}}
settingitem_bindsim.setOnClickListener(new MySettingItemListener());     }class MySettingItemListener implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(settingitem_bindsim.getChecked()){//check为true,则要设为false,这个setcheck也要去settingItem里暴露settingitem_bindsim.setCheck(false);                          }else{settingitem_bindsim.setCheck(true);           }}      }

接下里实现绑定,这要用到telephonyManager,拿到sim卡序列号,并传入private SharedPreferences

telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);sp = getSharedPreferences("config", MODE_PRIVATE);}class MySettingItemListener implements OnClickListener{@Overridepublic void onClick(View v) {// TODO Auto-generated method stubEditor editor = sp.edit();if(settingitem_bindsim.getChecked()){//check为true,则要设为false,这个setcheck也要去settingItem里暴露settingitem_bindsim.setCheck(false);//不获取,为空就好,参数为 ""editor.putString("simserial", ""); }else{settingitem_bindsim.setCheck(true);   //绑定sim卡的序列号,拿到,并传到SharedPreferencesString simserial=  telephonyManager.getSimSerialNumber();                editor.putString("simserial", simserial);}editor.commit();}       }

注意:这里需要readphone权限

这里要做一个数据的回显,每次进来的时候需要判断下是否有保存数据,否则每次进来都是未保存

telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);sp = getSharedPreferences("config", MODE_PRIVATE);if (sp.getString("simserial", "").length()!=0) {settingitem_bindsim.setCheck(true);}else {settingitem_bindsim.setCheck(false);}}

新功能,当重启手机后,sim卡变动,则发送短信提醒给一个联系人,重启会发出广播,要捕获到;当发出广播的时候,我们要同时知道是否sim发生变动,然后再调用系统API发送短信

获取已保存的,动态获取当前的,然后对比

若当前的序列号和保存的号不一样,则发送短信给一个绑定的手机号,而这个手机号是在activity3里完成的

还有一个问题,如果用户没有绑定sim卡,下一步进入3,此时为空,没法判断是卡变了还是没设置,所以应该在2里点击下一步时最好要判断下是否绑定了卡

@Overridepublic void next() {// TODO Auto-generated method stub//判断用户是否已经绑定,如果已经绑定,再继续执行,否则,提示一下用户,sim卡需要绑定。然后直接retrunif (sp.getString("simserial", "").length()==0) {Toast.makeText(this, "sim卡尚未绑定,请先绑定!", 0).show();return;}        Intent intent = new Intent(this, Setup3Activity.class);startActivity(intent);overridePendingTransition(R.anim.enteranim, R.anim.exitanim);finish();}

现在要在3里获取号码

给edittext加一个id

<EditTextandroid:id="@+id/et_setup3_phonenumber"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="请输入安全号码"/> 

然后要在Oncreate里获取

et_setup3_phonenumber = (EditText) findViewById(R.id.et_setup3_phonenumber);

从保存文件中获取号码,需要先判断用户是否获取联系人,若进来后直接next,应该提示用户,注意要return回到当前activity

@Overridepublic void next() {// TODO Auto-generated method stub//去获取电话号码,然后保存到sp中String phonenumber = et_setup3_phonenumber.getText().toString();if(phonenumber.isEmpty()){ Toast.makeText(this, "安全号码不能为空,请输入!", 0).show();return;}else {SharedPreferences sp =getSharedPreferences("config", MODE_PRIVATE);Editor editor=sp.edit();editor.putString("safenum", phonenumber);editor.commit();}       Intent intent = new Intent(this, Setup4Activity.class);startActivity(intent);overridePendingTransition(R.anim.enteranim, R.anim.exitanim);finish();}

这里需要一个新的包receiver,包含一个receiver,继承于broadcastreceiver,四大组件,需要去manifest声明

这里用静态注册

<receiver android:name="com.rjl.mobilephonemanager.receiver.BootCompleteReceiver"><intent-filter ><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver></application>
</manifest>

重启之后,会call到该方法;这里面需要实现的是,要获取之前保存的sim卡 序列号;获取当前插入的sim卡的序列号;对比,如果发现不一致,则向指定号码发送报警短信

注意,这里无法直接调用SharedPreferences,之前的比如setup2里面能使用,虽然他自己没有定义这样的方法,但是他的父类或者父的父当中应该有,而这里的receiver里是没有的,但是可以通过上下文去获取,他本身就传递一个上下文

如果没设置,置空,就不会发通知

public class BootCompleteReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stub//重启之后,会call到该方法//这里面需要实现的是,要获取之前保存的sim卡 序列号    System.out.println("BootCompleteReceiver.onReceive() 开机重启事件收到");SharedPreferences sp =  context.getSharedPreferences("config", context.MODE_PRIVATE);if (sp.getBoolean("enable_protect", false)) {String simserial_saved = sp.getString("simserial", "");String safenum = sp.getString("safenum", "");//获取当前插入的sim卡的序列号TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);String simserial_now=  telephonyManager.getSimSerialNumber();// 对比,如果发现不一致,则向指定号码发送报警短信if (!simserial_now.equals(simserial_saved)) {//发送报警短信//SmsManager smsManager ;//= context.getSystemService(context.)SmsManager smsManager = SmsManager.getDefault();//调用该类的如下API去发送短信//其中,目前仅需要了解第一个参数为短信发送号码,第二个参数为短信内容,其他可以不填      smsManager.sendTextMessage(safenum, null, "我是报警短信!", null, null);  System.out.println("BootCompleteReceiver.onReceive() 检测到sim变更");}}}
}

权限

    <uses-permission android:name="android.permission.SEND_SMS"/><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

这里也有回显问题,要在setup3里面oncreate时判断下

@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_setup3);et_setup3_phonenumber = (EditText) findViewById(R.id.et_setup3_phonenumber);//et的数据回显操作SharedPreferences sp =getSharedPreferences("config", MODE_PRIVATE);et_setup3_phonenumber.setText(sp.getString("safenum", "")); }

要去4里面保存设置,需要checkbox

ID

<CheckBox android:id="@+id/cb_setup4_enableprotect"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="您还没有开启手机防盗保护"/>

找到

public class Setup4Activity extends SetupBaseActivity {private SharedPreferences sp ;CheckBox cb_setup4_enableprotect;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_setup4);cb_setup4_enableprotect = (CheckBox) findViewById(R.id.cb_setup4_enableprotect);}

listener 这里有两个,一个是状态改变的,一个是点击的,都可以,但前者更适用一点,返回当前状态,后者是返回一个view,再通过view找到状态

另外还需要回显

public class Setup4Activity extends SetupBaseActivity {private SharedPreferences sp ;CheckBox cb_setup4_enableprotect;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_setup4);cb_setup4_enableprotect = (CheckBox) findViewById(R.id.cb_setup4_enableprotect);//回显sp = getSharedPreferences("config", MODE_PRIVATE);if (sp.getBoolean("enable_protect", false)) {cb_setup4_enableprotect.setChecked(true);cb_setup4_enableprotect.setText("防盗保护已经开启!");}else {cb_setup4_enableprotect.setChecked(false);cb_setup4_enableprotect.setText("防盗保护尚未开启!");}cb_setup4_enableprotect.setOnCheckedChangeListener(new OnCheckedChangeListener() {     @Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {// TODO Auto-generated method stubsp=getSharedPreferences("config", MODE_PRIVATE);Editor editor = sp.edit();if (isChecked) {//说明用户开启了防盗保护,需要保存状态   editor.putBoolean("enable_protect", true);cb_setup4_enableprotect.setText("防盗保护已经开启!");}else {//说明用户没开启防盗保护,需要保存状态editor.putBoolean("enable_protect", false);cb_setup4_enableprotect.setText("防盗保护尚未开启!");}editor.commit();}});}

再回到lostfind完善设置过的显示

if (sp.getBoolean("setupcomplete", false)) {//设置过TextView  tv_lostfind_safenum  = (TextView) findViewById(R.id.tv_lostfind_safenum);tv_lostfind_safenum.setText(sp.getString("safenum", ""));         ImageView iv_lostfind_lockstatus = (ImageView) findViewById(R.id.iv_lostfind_lockstatus);if (sp.getBoolean("enable_protect", false)) {iv_lostfind_lockstatus.setImageResource(R.drawable.lock);}else {iv_lostfind_lockstatus.setImageResource(R.drawable.unlock);}   

最后获取联系人信息,需要contentprovider,通过URI访问数据库返回一个cursor,遍历cursor,转到bean里,再在bean里获取

会弹出一个listview,在这个view里选择,选好了要关掉自己回到当前activity,选好了要放到textview里,这就是两个activity之间的数据传递,这又用到intent

首先需要一个联系人列表list

layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" >   <TextViewandroid:layout_width="fill_parent"android:layout_height="60dp"android:text="联系人列表"android:textSize="25sp"android:gravity="center"/><ListViewandroid:id="@+id/listview_contactslist"android:layout_width="fill_parent"android:layout_height="fill_parent"/>
</LinearLayout>

activity,需要一个adapter

public class ContactsListAcitvity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.actvity_contactslist);ListView  listview_contactslist = (ListView) findViewById(R.id.listview_contactslist);listview_contactslist.setAdapter(new MylistAdapter());}class MylistAdapter extends BaseAdapter{@Overridepublic int getCount() {// TODO Auto-generated method stubreturn 0;}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubreturn null;}        }
}

弹出来的view  布局 contactslist_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_contactlist_name"android:layout_width="match_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/tv_contactlist_number"android:layout_width="match_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/tv_contactlist_email"android:layout_width="match_parent"android:layout_height="wrap_content"/>
</LinearLayout>

要在adapter的getView里去获取然后填充

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubView v = View.inflate(ContactsListAcitvity.this, R.layout.contactslist_item, null);TextView tv_contactlist_name = (TextView) v.findViewById(R.id.tv_contactlist_name);TextView tv_contactlist_number = (TextView) v.findViewById(R.id.tv_contactlist_number);TextView tv_contactlist_email = (TextView) v.findViewById(R.id.tv_contactlist_email);return null;}       

list里是一个bean,之前在contentprovider里写过,套件,拿来用

public class Contact {//这里必须要给个空值"",有别于null,null会报空指针异常private String name="";private String number="";private String email="";public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Contact(String name, String number, String email) {super();this.name = name;this.number = number;this.email = email;}public Contact() {super();// TODO Auto-generated constructor stub}@Overridepublic String toString() {return "Contact [name=" + name + ", number=" + number + ", email="+ email + "]";}
}

现在这个可以拿来查,但是可以抽出来作为一个单独的业务逻辑,让别人用,抽成一个类放到工具类,返回联系人列表

public class GetContactsList {//getContentResolver需要在上下文中获取,需要在get时传进一个contextpublic static List<Contact> get(Context context){List<Contact> list = new ArrayList<Contact>();ContentResolver cr = context.getContentResolver();        Cursor c =cr.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{ "contact_id"}, null, null, null);while(c.moveToNext()){int id = c.getInt(0); Cursor c2 =cr.query(Uri.parse("content://com.android.contacts/data"), new String[]{"mimetype" ,"data1"}, "raw_contact_id=?", new String[]{id+""}, null); //c2Contact contact = new Contact();while (c2.moveToNext()) {String type =  c2.getString(0);String data1 = c2.getString(1); if ("vnd.android.cursor.item/name".equals(type)) {contact.setName(data1);}if ("vnd.android.cursor.item/phone_v2".equals(type)) {contact.setNumber(data1);}if ("vnd.android.cursor.item/email_v2".equals(type)) {contact.setEmail(data1);} }//防止数据库里有空数据if (!contact.getName().isEmpty()) {list.add(contact);}Log.i("getContact", contact.toString());}return list;      }
}

在contactlistactivity里晚上获取

ublic class ContactsListAcitvity extends Activity {List<Contact> list ;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.actvity_contactslist);ListView  listview_contactslist = (ListView) findViewById(R.id.listview_contactslist);list= GetContactsList.get(this);listview_contactslist.setAdapter(new MylistAdapter());}class MylistAdapter extends BaseAdapter{@Overridepublic int getCount() {// TODO Auto-generated method stubreturn list.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// 根据position来获取联系人Contact contact = list.get(position);View v = View.inflate(ContactsListAcitvity.this, R.layout.contactslist_item, null);TextView tv_contactlist_name = (TextView) v.findViewById(R.id.tv_contactlist_name);TextView tv_contactlist_number = (TextView) v.findViewById(R.id.tv_contactlist_number);TextView tv_contactlist_email = (TextView) v.findViewById(R.id.tv_contactlist_email);tv_contactlist_name.setText(contact.getName());tv_contactlist_number.setText(contact.getNumber());tv_contactlist_email.setText(contact.getEmail());return v;}       }
}

在activity3拿到联系人信息

public void selectpeople(View v){//需要实现从系统的联系人里获取一个联系人信息Intent intent = new Intent(this,ContactsListAcitvity.class);startActivity(intent); }

activity的声明

 <activity android:name=".ContactsListAcitvity"></activity>

访问系统联系人的权限

<uses-permission android:name="android.permission.READ_CONTACTS"/>

点那个联系人要退出,然后把结果给setup3

则启动时不能直接intent,而是forresult

public void selectpeople(View v){//需要实现从系统的联系人里获取一个联系人信息Intent intent = new Intent(this,ContactsListAcitvity.class);startActivityForResult(intent, 100);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stub        super.onActivityResult(requestCode, resultCode, data);}

弹出的list里面需要listener

listview_contactslist.setOnItemClickListener(new MyOnItemClickListener());}class MyOnItemClickListener implements OnItemClickListener{@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {//根据位置获取联系人Contact contact=  list.get(position);//只需显示numberString number = contact.getNumber();      //通过intent返回Intent intent = new Intent();intent.putExtra("number", number);//resultcode自己定setResult(200, intent);    finish();}        }

activity3要接收这边的返回

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stub      if (requestCode==100&&resultCode==200) {String number =data.getStringExtra("number");et_setup3_phonenumber.setText(number); }super.onActivityResult(requestCode, resultCode, data);}

丛实际应用来说,当联系人过多的时候,显示列表的时候,因为是在oncreate里,有可能会引发主线程的阻塞,最好放在子线程里面操作

public class ContactsListAcitvity extends Activity {List<Contact> list ;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.actvity_contactslist);ListView  listview_contactslist = (ListView) findViewById(R.id.listview_contactslist);//当联系人过多的时候,此处有可能会引发主线程的阻塞//最好放在子线程里面操作list= GetContactsList.get(this);        listview_contactslist.setAdapter(new MylistAdapter());listview_contactslist.setOnItemClickListener(new MyOnItemClickListener());        }

最后来实现监听广播

防盗保护开启,换了卡,收到短信,回一条短信

要location;或者让他播音乐,方便发现;或者删除数据;或者锁屏

故而本手机上需要一个短信拦截小助手,要知道紧急联系人回的短信里附带了什么样的指令

broadCastReceiver,需要在manifest里注册和权限,在声明里面需要加上最高权限1000,否则有可能被系统看到,那么小偷就能收到

<receiver android:name="com.rjl.mobilephonemanager.receiver.SMSReceiver"><intent-filter android:priority="1000"><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>

看看之前的短信拦截,copy过来改动一下,加上trace看一下

public class SMSReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubSystem.out.println("MySmsReceiver. onReceive() 我收到新的短信了");Bundle bundle =  intent.getExtras();//pdus是一个object数组,短信数组,被分成多条的短信再组合起来Object[] obj =   (Object[]) bundle.get("pdus");//将短信取出来,需要把object强转成数组for (Object object : obj) {SmsMessage  sms = SmsMessage.createFromPdu((byte[])object);String addr = sms.getOriginatingAddress();String body = sms.getMessageBody();System.out.println("MySmsReceiver. onReceive()短信的具体内容是" +addr+":"+body);              if ("10086".equals(addr)) {abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);}    else if("#*alarm*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);}  else if("#*wipedata*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);}    else if("#*lockscreen*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);}                   }    }
}

但是注意

在4.3和4.3以下版本,可以收到短信,也可以拦截
在4.4 及以上版本,可以收到短信,但是无法拦截

安卓将接口隐藏了,但是也可以通过代码去调动这个接口

Intent intent = new Intent();
intent.setClassName("com.android.settings","com.android.settings.Settings");
intent.setAction(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_CLEAR_TASK| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT,"com.android.settings.applications.AppOpsSummary");
startActivity(intent);
FLAG_ACTIVITY_NEW_TASK: 设置此状态, 首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈
如果有,刚直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity
关于播放音乐有两种写法,音乐文件放在SD卡上
else if("#*alarm*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);MediaPlayer mp = new MediaPlayer();            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);try {mp.setDataSource("storage/sdcard/bajie.mp3");mp.setLooping(true);mp.prepare();mp.start();          } catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}             } 

音乐文件放在工程里,或者说APP里,需要新建一个raw的文件夹

防止声音调的低,用代码调到最高,需要AudioManager,是一个service
else if("#*alarm*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);MediaPlayer player = MediaPlayer.create(context,R.raw.bajie);// 不需要重新准备player.setLooping(true);//对音乐的管理,用代码调到最大AudioManager manager=(AudioManager) context.getSystemService(Context.AUDIO_SERVICE);int max=manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);// 1 声音的类型  2 声音的大小manager.setStreamVolume(AudioManager.STREAM_MUSIC, max, 0);player.start();// 播放          } 

获取location,调用当前GPS接口,获得坐标信息保存起来

网络定位在web早起用得比较多,由于现在IP的数量级巨大,通过子网链接,比较乱,定不准,无法精确定位,现在会用基站定位,根据与各个基站位置来定位
虽然只能与一个基站通信,其实可以连接到很多基站,基站的覆盖范围很广,会有交叉
不过更好的是GPS定位
由于启动location是要时间的,我们在代码里不能一声明了LocationManager就往下执行,这样会出错,所以需要一个callback,说我启动好了,更新了坐标,再往下执行

这里需要传一个locationListener

这整个过程比较耗时,不应该放到广播的onReceive里面,而短信的这个广播是一个有序广播,按照优先级,安卓要求必须很快传递数据,可以去写一个service

这里可以用线程,但是线程安全性低一些,可能会被干掉

我们要在service里获取到经纬度信息,保存到SharedPreferences,然后在receiver里读取到这个经纬度,通过短信发送出去

location需要权限

<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_MOCK_LOCATION"/>

service

public class LocationService extends Service {@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stub     return null;}@Overridepublic void onCreate() {// TODO Auto-generated method stubLocationManager manager =(LocationManager) getSystemService(LOCATION_SERVICE);          manager.requestLocationUpdates("gps",0, 0, new MyLocationListener());super.onCreate();}class  MyLocationListener implements LocationListener{@Overridepublic void onLocationChanged(Location location) {// TODO Auto-generated method stub//获取经纬度double Latitude = location.getLatitude();double Longitude = location.getLongitude();//保存起来SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);Editor editor = sp.edit();editor.putString("Latitude", Latitude+"");editor.putString("Longitude", Longitude+"");editor.commit();}@Overridepublic void onStatusChanged(String provider, int status, Bundle extras) {// TODO Auto-generated method stub          }@Overridepublic void onProviderEnabled(String provider) {// TODO Auto-generated method stub           }@Overridepublic void onProviderDisabled(String provider) {// TODO Auto-generated method stub          }       }
}

receiver

 if ("#*location*#".equals(addr)) {abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);//获取到这个serviceIntent service = new Intent(context, LocationService.class);context.startService(service);//从SharedPreferences中读取SharedPreferences sp = context.getSharedPreferences("config", context.MODE_PRIVATE);String Latitude = sp.getString("Latitude", "");String Longitude =  sp.getString("Longitude","");               System.out.println("SMSReceiver.onReceive()"+Latitude+"/"+Longitude);//获取系统提供的短信管理类SmsManager smsManager = SmsManager.getDefault();//调用该类的如下API去发送短信//其中,目前仅需要了解第一个参数为短信发送号码,第三个参数为短信内容,其他可以不填smsManager.sendTextMessage("5556", null, Latitude+"/"+Longitude, null, null);}

这里启动时,就去获取经纬度,很可能是无法获取到的,因为还在启动,可以让他在线程里等一会,但是讨巧的做法是发送一个短信去启动后,过一会再发一条,这时就可以接收到

擦除数据和锁屏都要DevicePolicyManager

这里肯定要权限,但是不是常见的permission,而是超级管理员

这一部分以一个一键锁屏的demo演示一下 点击一个button就能锁屏

layout

<Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView1"android:layout_below="@+id/textView1"android:layout_margin="36dp"android:text="Button"android:onClick="lockscreen"/>

mainactivity

public class MainActivity extends Activity {private DevicePolicyManager manager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);manager =(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);     }public void lockscreen(View v){manager.lockNow();}
}

此时若点击按钮,显然会出错,要超级管理员
首先他需要一个广播接收者,DeviceAdminReceiver,然后要一个子类继承他,新建一个AdminReceiver,这里面什么代码都不需要,为什么要放到这个receiver里?激活管理员权限,系统会发一个广播给应用,这个子类的父类会去修改权限

import android.app.admin.DeviceAdminReceiver;public class AdminReceiver extends DeviceAdminReceiver {}

这时候要去manifest里声明

<receiver android:name=".AdminReceiver"         android:label="@string/sample_device_admin"         android:description="@string/sample_device_admin_description"         android:permission="android.permission.BIND_DEVICE_ADMIN">     <meta-data android:name="android.app.device_admin"             android:resource="@xml/device_admin_sample" />     <intent-filter>         <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />     </intent-filter> </receiver>

这里面需要注意,有几个要在values下的string下声明

<?xml version="1.0" encoding="utf-8"?>
<resources><string name="app_name">锁屏小应用</string><string name="hello_world">Hello world!</string><string name="action_settings">Settings</string><string name="sample_device_admin">一键锁屏小应用</string><string name="sample_device_admin_description">一键锁屏小应用:给力</string>
</resources>

需要一个权限,已经在里面了

然后metadata,一般在head里定义的源信息,里面有一个resource,需要新建一个folder

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">   <uses-policies>            <reset-password />     <force-lock />     <wipe-data />      </uses-policies>
</device-admin>

现在声明好了,还需要去激活

不过这个在模拟器上会重启,在真机上可以

OK,现在来完成锁屏和除数据

将锁屏小应用的相关信息弄过来,string,manifest声明,xml文件夹

注意改一下name

<receiver android:name=".receiver.AdminReceiver"         android:label="@string/sample_device_admin"         android:description="@string/sample_device_admin_description"         android:permission="android.permission.BIND_DEVICE_ADMIN">     <meta-data android:name="android.app.device_admin"             android:resource="@xml/device_admin_sample" />     <intent-filter>         <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />     </intent-filter> </receiver>
<?xml version="1.0" encoding="utf-8"?>
<resources><string name="app_name">MobilePhoneManager</string><string name="hello_world">Hello world!</string><string name="action_settings">Settings</string><string name="sample_device_admin">手机管家</string><string name="sample_device_admin_description">开启远程锁屏和擦除数据</string>
</resources>

要在SMSReceiver里去实现,但是要判断用户是否激活了

else if("#*wipedata*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);ComponentName who=new ComponentName(context, AdminReceiver.class);if(manager.isAdminActive(who)){manager.wipeData(0);}       }    else if("#*lockscreen*#".equals(body)){abortBroadcast();  System.out.println("SMSReceiver.onReceive()"+body);ComponentName who=new ComponentName(context, AdminReceiver.class);if(manager.isAdminActive(who)){manager.wipeData(0);}}     

需要提前激活这个手机管家的权限,各种权限是在xml那个文件里定义的

这一块就基本完成了,但是最好能用代码去开启权限,而不是让用户自己开启,一般都不愿意,在原来的setup4里面有个textview,可以加上一个onclick响应

<TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="激活超级管理员\n您就可以远程擦除数据"android:padding="5dp" android:background="@drawable/textbg_setup4"android:textSize="18sp" android:layout_margin="5dp"android:onClick="active"android:clickable="true"android:focusable="true"/>
public void active(View v){Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);         ComponentName mDeviceAdminSample=new ComponentName(this, AdminReceiver.class);intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);    intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"激活后才可以锁屏,如果不激活罚2000块钱");startActivity(intent);}

此时就直接跳转到激活,这里其实可以做一个判断,如果之前激活过,给一个提示。

获得了管理员权限后就不能直接卸载了,需要反激活再卸载,但是用户会嫌麻烦

可以在APP里加一个button,让他自己卸载,

卸载就是给一个包名然后destroy(),

关键是反激活,需要在SMSreceiver里调用removeActiveAdmin

[安卓]手机管家(八)防盗之业务逻辑相关推荐

  1. 安卓强制恢复出厂_看过来!这是让安卓手机十八个月不卡的秘诀

    虽然苹果手机售价高昂,外观设计万年不变,但是却仍然有着不少消费者选择使用iPhone,为什么这些消费者会选择iPhone?个人觉得还是因为苹果系统的体验实在太流畅. 反观安卓阵营,尽管安卓手机早已摆脱 ...

  2. [安卓]手机管家(十)正则表达式 号码归属地

    校验QQ号码 必须5-15位数字 0不能开头 纯代码式 import java.util.Scanner; public class RegExpDemo {public static void ma ...

  3. 【腾讯TMQ】【测试左移专栏】手机管家PiTest测试左移实践

    作者:CC 团队:腾讯移动品质中心TMQ [引入] 说起"测试左移"相信对于大家来说已经不再陌生,左移的也手段非常多,无论是使用NLP来做需求分析,还是使用ACC来做测试建模,目的 ...

  4. 安全管家安卓_手机丢失后可能背负巨额债务,腾讯手机管家提醒注意手机安全防护 -...

    之前骗子偷手机是为了卖手机换钱,现在骗子偷手机,是为了用你的信息各平台套现.近期,一篇名为<一部手机失窃而揭露的窃取个人信息实现资金盗取的黑色产业链>引发广泛关注,工信部约谈相关单位,并提 ...

  5. 手机发送验证码的业务逻辑探究-主要是安全性,响应性

    手机发送验证码的业务逻辑探究-主要是安全性,响应性 这样一来,只要知道静态的验证码是什么,脚本就可以轻松填写正确的验证码. 解决方法: 1后台是否可以限制一个IP发送的次数 2限定发送验证码的一分钟的 ...

  6. 安全管家安卓_安卓手机自带的管家好,还是另外获取的管家好呢?这4点你要知道...

    安卓手机自带的管家好,还是另外获取的管家好呢?这4点你要知道 目前使用安卓手机朋友们,应该都很熟悉自己的手机带有手机管家这个功能(不同的手机有可能叫法不同),但是也是有不少用户,因为某些原因会另外获取 ...

  7. 安卓最新版本_腾讯手机管家下载最新版本-腾讯手机管家2020新版本下载v8.8.1 安卓官方版...

    2020腾讯手机管家安卓版是一款功能强大的安全优化软件,让你的手机处在安全的网络环境中,抵抗外界的干扰,还能智能拦截骚扰电话,给你一个干净舒适的环境,更多功能尽在腾讯手机管家客户端.喜欢的朋友就来22 ...

  8. qq手机令牌 for android3.3 官方安装版,腾讯手机管家app下载 腾讯手机管家(原QQ手机管家) for Android v8.8.3 官方安卓版 下载-脚本之家...

    腾讯手机管家(原QQ手机管家)是一款手机安全客户端软件,QQ手机管家主要功能是防QQ帐号被盗.防骚扰.防泄密,以及颇具创新的"云端保护精准拦截"功能,但并没有加入上网流量监控.手机 ...

  9. android10禁用华为桌面,[原创]简单分析华为emui10对第三方桌面的禁用逻辑(华为手机管家app) + 求助新rom的分析入手思路...

    华为开启emui10的公测后, 之前一直禁止切换默认launcher的情况有了新的解决办法 : 冻结 手机管家 即可设置 第三方launcher 这里简单分析华为手机管家中 相关逻辑 求助: 在 最新 ...

最新文章

  1. 关于commonjs,AMD,CMD之间的异同
  2. boot的几个依赖 spring_Spring boot依赖管理和数据库使用
  3. linux命令的基本操作
  4. android系统底层驱动多个物理按键上报同一个键值给app层,app层如何区分
  5. Kotlin中的接口回调
  6. SpringBoot——@Scheduled的自定义周期性线程池解决任务延时执行问题
  7. 计算机视觉基础-图像处理(图像分割/二值化)cpp+python
  8. python内核死亡的原因_Python xgboost:内核死亡
  9. R语言如何并行处理[parallel package][向量化操作并行优化]
  10. 如何注册苹果开发者账号
  11. 使用dsoFramer开始Office应用程序
  12. 【滤波器】基于时变维纳滤波器实现语音去噪含Matlab源码
  13. Python替换月份为英文缩写
  14. 谷粒学院P21所需的maven jar包
  15. Solr高级查询Facet
  16. PMP考试 工作绩效数据 工作绩效信息 工作绩效报告 区别与联系
  17. 中国程序员的真实工资亦或幸福指数
  18. minio服务器在win10的上传与下载,以及修改头像Minio速看免费本地文件服务器
  19. 【嵌入式】——串口实验——实现芯片串口收发数据,按键中断串口发送数据,串口接收数据中断来控制LED亮/灭
  20. mean shift:从图像分割到特征空间分析

热门文章

  1. 计算机开头,计算机论文开头
  2. OM | 运筹学在医疗运营管理中的应用
  3. wins下GetLastError错误码说明
  4. 机器学习的意义(转载)
  5. Windows系统下的PDF编辑工具软件-PDF编辑器下载
  6. Pandas库——DataFrame入门
  7. SQL之统计某一状态数量
  8. 基于MTK 的 TP 驱动分析
  9. 基于FPGA的ASK/FSK调制
  10. linux内核 猪头 作用,Linux内核驱动之一些重要数据结构