返回 登录
0

缔造Android推送服务不死之身

以后自己会用到这个记录一下
废话就不多说了,直奔主题:
首先是推送的配置,这里就不在叙述:使用的是androidpn;github中有源码,这里不是本贴的重点:

1.首先弄明白两点:
(1)当资源不够用的时候,手机的服务可能被kill掉,
(2)当手机重启的时候,应用的服务是没有被开启的;也就是你不打开应用,服务不会自动开启

根据以上两点,我们可以对症下药;

N1:提供一个工具类:主要判断服务的开启,应用的前后台的运行情况、开启广播监听,每一分钟检测一次开启推送服务等

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;

/**
* 静态工具类:主要判断服务的开启,应用的前后台的运行情况、开启广播监听,每一分钟检测一次开启推送服务等

  • @author wangl(Mail:WangleiDree@gmail.com)
    */
    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);
      }

    /**

    • 获取设备的deviceId用来做推送username
    • @param context
    • @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();
      

      }

}

N2:定义广播接收者,定时判断服务有没有开启

/**
* 广播接受者 定时判断开启服务

  • @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------------>>>>>>>>");
    }
    

    }

N3:定义一个广播接受者:当机器重启了 ,那么使用这个广播接收者来循环调用开启服务

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 手机重启————>>>>>>>>”);

N4:配置manifest文件:主要是广播和服务(根据实际包名定义)

    <!-- 定时开启服务的广播 -->
    <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>
评论