缔造Android推送服务不死之身

jmxyandy 9年前
   <p>以后自己会用到这个记录一下</p>    <p>废话就不多说了,直奔主题:</p>    <p>首先是推送的配置,这里就不在叙述:使用的是androidpn;github中有源码,这里不是本贴的重点:</p>    <p>1.首先弄明白两点:</p>    <p>(1)当资源不够用的时候,手机的服务可能被kill掉,</p>    <p>(2)当手机重启的时候,应用的服务是没有被开启的;也就是你不打开应用,服务不会自动开启</p>    <p>根据以上两点,我们可以对症下药;</p>    <p>N1:提供一个工具类:主要判断服务的开启,应用的前后台的运行情况、开启广播监听,每一分钟检测一次开启推送服务等</p>    <pre>  <code class="language-java">import java.util.List;   import android.app.ActivityManager;   import android.app.ActivityManager.RunningAppProcessInfo;   import android.app.AlarmManager;   import android.app.PendingIntent;   import android.content.ComponentName;   import android.content.Context;   import android.content.Intent;   import android.content.SharedPreferences;   import android.content.SharedPreferences.Editor;   import android.telephony.TelephonyManager;   import android.text.TextUtils;   import com.mc.androidpn.client.Constants;   import com.mc.androidpn.client.ServiceManager;   import com.mc.mycardlicense.activity.R;   import com.mc.mycardlicense.receiver.PushAlarmReceiver;    /**   * 静态工具类:主要判断服务的开启,应用的前后台的运行情况、开启广播监听,每一分钟检测一次开启推送服务等    public class CommonStaticUtil {       private static final String TAG = "CommonStaticUtil";       /**         * 用来判断服务是否在运行.         * @param mContext 上下文         * @param className 判断的服务名字         * [url=home.php?mod=space&uid=309376]@return[/url] isRunning :true 在运行 、false 不在运行         */       public static boolean isServiceRunning(Context mContext, String className) {           //默认标记:为false           boolean isRunning = false;           ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);           //获取正在运行的服务           List<ActivityManager.RunningServiceInfo> serviceList = activityManager.getRunningServices(30);           //如果没有,那么返回false           if (!(serviceList.size() > 0)) {                return false;           }           //如果有,那么迭代List,判断是否有当前某个服务           for (int i = 0; i < serviceList.size(); i++) {               if (serviceList.get(i).service.getClassName().equals(className) == true) {                    isRunning = true;                    break;               }           }           return isRunning;      }       /**       * 判断程序是否在当前前台运行       *       * @return true程序在当前前台运行、false的时候程序不在当前前台运行       */      public static boolean isRunningForeground (Context context){           ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);           //The activity component at the top of the history stack of the task. This is what the user is currently doing.           ComponentName cn = am.getRunningTasks(1).get(0).topActivity;           String currentPackageName = cn.getPackageName();           if(!TextUtils.isEmpty(currentPackageName) && currentPackageName.equals(context.getPackageName()))           {                 return true ;           }           return false ;       }         /**         * 程序是否在前台队列中运行         * @param mContext 上下文         * @return true 标识是在队列里、false标识不在前台桟列         */       public static boolean isAppOnForeground(Context mContext) {           // Returns a list of application processes that are running on the device           ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);           String packageName = mContext.getApplicationContext().getPackageName();           List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();           if (appProcesses == null)                return false;           for (RunningAppProcessInfo appProcess : appProcesses) {                // The name of the process that this object is associated with.                if (appProcess.processName.equals(packageName)&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {                     return true;                }           }           return false;      }        /**        * 开启后台推送服务        * @param context 上下文        */      public static void startService(Context context){           Logger.i(TAG, "----startService-class----------------");           if(!CommonStaticUtil.isServiceRunning(context, StaticMember.SERVICENAME)){                Logger.i(TAG, "Service 没有开启,开启推送服务........>");                ServiceManager serviceManager = new ServiceManager(context);                serviceManager.setNotificationIcon(R.drawable.ic_launcher);                serviceManager.startService();           }else{                Logger.i(TAG, "Service 推送服务已开启........>");           }      }        /**        * 关闭 推送服务        * @param context 上下文        */      public static void stopService(Context context){           Logger.i(TAG, “关闭 推送服务……..”);           // 关闭推送服务           ServiceManager serviceManager = new ServiceManager(context);           serviceManager.setNotificationIcon(R.drawable.ic_launcher);           serviceManager.stopService();           //删除配置文件           SharedPreferences preferences = context.getSharedPreferences(Constants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE);           Editor editor = preferences.edit();           editor.clear();           editor.commit();       }      /**        开启广播监听,每一分钟检测一次开启推送服务          @param context 上下文传递 */        public static void startReceiver(Context context){             Logger.i(TAG, “开启广播监听……..”);             AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);             Intent intent2 = new Intent(context, PushAlarmReceiver.class);             //发送一个广播             PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0, intent2, 0);             //1分钟定时重复发送–:即一分钟检测一次服务有没有开启,没有开启就开启服务             alarmManager.setRepeating(AlarmManager.RTC, 0, 60 * 1000,pendingIntent);        }          /**   <li>获取设备的deviceId用来做推送username</li>   <li>@param context</li>   <li>@return 返回设备的DeviceID号        */       public static String getDeiviceID(Context context){            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);            /*             * 唯一的设备ID:             * GSM手机的 IMEI 和 CDMA手机的 MEID.             * Return null if device ID is not available.             */            return tm.getDeviceId();      }  }</code></pre>    <p>N2:定义广播接收者,定时判断服务有没有开启</p>    <pre>  <code class="language-java">/**   * 广播接受者 定时判断开启服务    @author wangl(Mail:WangleiDree@gmail.com)   */  public class PushAlarmReceiver extends BroadcastReceiver {       private static final String TAG = “PushAlarmReceiver”;       private Context context;       private static int count=0;//1分钟检测下后台服务是否开启       @Override       public void onReceive(Context context, Intent intent) {            this.context = context;            Log.i(TAG, "-----------------1 minutes to in------------>>>>>>>>");            CommonStaticUtil.startService(context);              Log.i(TAG, "-----------------1 minutes to out------------>>>>>>>>");        }  }</code></pre>    <p>N3:定义一个广播接受者:当机器重启了 ,那么使用这个广播接收者来循环调用开启服务</p>    <pre>  <code class="language-java">package com.mc.mycardlicense.receiver;    import android.app.AlarmManager;   import android.app.PendingIntent;   import android.content.BroadcastReceiver;   import android.content.Context;   import android.content.Intent;   import android.util.Log;    import com.mc.mycardlicense.utils.CommonStaticUtil;   import com.mc.mycardlicense.utils.Logger;   /**   * 广播接收者:当机器重启了 ,那么使用这个广播接收者来循环调用开启服务    @author wangl(Mail:WangleiDree@gmail.com)  */   public class PushStartupReceiver extends BroadcastReceiver {        private static final String TAG = “PushStartupReceiver”;        @Override        public void onReceive(Context context, Intent intent) {            // TODO Auto-generated method stub            Log.i(TAG, “—————–PushStartupReceiver in 手机重启————>>>>>>>>”);        }  }</code></pre>    <p>N4:配置manifest文件:主要是广播和服务(根据实际包名定义)</p>    <pre>  <code class="language-java"><!-- 定时开启服务的广播 -->   <receiver        android:name="com.mc.mycardlicense.receiver.PushAlarmReceiver"        android:enabled="true" />          <!-- 手机重启的广播 -->        <receiver android:name="com.mc.mycardlicense.receiver.PushStartupReceiver" >              <intent-filter android:priority="1000" >              <category android:name="android.intent.category.HOME" />                <action android:name="android.intent.action.BOOT_COMPLETED" > </action>              </intent-filter>        </receiver></code></pre>    <p> </p>    <p>来自:http://www.androidchina.net/5525.html</p>    <p> </p>