/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.extension.push; import java.util.List; import java.util.Properties; import java.util.Random; import org.jivesoftware.smack.NotificationIQ; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.packet.Packet; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import com.polyvi.xface.R; import com.polyvi.xface.event.XEvent; import com.polyvi.xface.event.XEventType; import com.polyvi.xface.event.XSystemEventCenter; import com.polyvi.xface.extension.XExtensionContext; import com.polyvi.xface.util.XConstant; /** * 该类继承与Service主要是读取配置文件,然后去连接服务器 */ public class XNotificationService extends Service { /** 通知显示的action名 */ private static final String ACTION_SHOW_NOTIFICATION = "com.polyvi.push.SHOW_NOTIFICATION"; /** 通知被点击的action名 */ private static final String ACTION_NOTIFICATION_CLICKED = "com.polyvi.push.NOTIFICATION_CLICKED"; /** 通知被取消的action名 */ private static final String ACTION_NOTIFICATION_CLEARED = "com.polyvi.push.NOTIFICATION_CLEARED"; /** 通知的id名 */ private static final String NOTIFICATION_ID = "id"; /** 通知的apikey名 */ private static final String NOTIFICATION_API_KEY = "apiKey"; /** 通知的title名 */ private static final String NOTIFICATION_TITLE = "title"; /** 通知的内容名 */ private static final String NOTIFICATION_MESSAGE = "message"; /** 通知的uri名 */ private static final String NOTIFICATION_URI = "uri"; /** 配置文件中存储登陆服务器主机的名字 */ private static final String HOST = "host"; /** 配置文件中存储登陆服务器端口的名字 */ private static final String PORT = "port"; /** 配置文件中存储是否开启push的名字 */ private static final String IS_OPEN_PUSH = "isOpenPush"; /** 配置文件存储的名字 */ private static final String FILE_NAME = "push"; /** 配置文件所在工程的目录名字 */ private static final String FILE_DIRECTORY = "raw"; /** 电话状态管理 */ private TelephonyManager mTelephonyManager; /** 收到通知广播 */ private BroadcastReceiver mNotificationReceiver = null; /** 网络状态改变的广播 */ private BroadcastReceiver mConnectivityReceiver = null; /** 电话状态改变监听 */ private PhoneStateListener mPhoneStateListener = null; /** push的连接管理 */ private XConnectionManager mConnectionManager; /** 收到从服务器发过来通知请求的监听,主要实现发送通知广播 */ private PacketListener mNotificationPacketListener; /** 通知管理 */ private NotificationManager mNotificationManager; private Properties mProps; private static String mPackageName; private static String mHost; private static String mPort; public XNotificationService() { } @Override public void onCreate() { init(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (null == mPackageName) { mPackageName = intent.getStringExtra(XServiceManager.PACKAGE_NAME); mHost = intent.getStringExtra(XServiceManager.HOST); mPort = intent.getStringExtra(XServiceManager.PORT); } return Service.START_REDELIVER_INTENT; } /** * 主要实现一些初始化的操作 */ private void init() { mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); mProps = openProperties(this); mConnectionManager = new XConnectionManager(this); registerNotificationReceiver(); registerConnectivityReceiver(); mConnectionManager.connect(); } /** * 对电话状态监听,当手机网络从断开到连接的时候去连接服务器 */ private void genPhoneStateListener() { if (null == mPhoneStateListener) { mPhoneStateListener = new PhoneStateListener() { @Override public void onDataConnectionStateChanged(int state) { super.onDataConnectionStateChanged(state); if (state == TelephonyManager.DATA_CONNECTED) { connect(); } } }; } } /** * 对接收到通知进行处理:1.显示通知;2.点击通知;3.清除通知 */ private void genNotificationReceiveBroadcastReceive() { if (null == mNotificationReceiver) { mNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_SHOW_NOTIFICATION.equals(action)) { String notificationId = intent .getStringExtra(NOTIFICATION_ID); String notificationApiKey = intent .getStringExtra(NOTIFICATION_API_KEY); String notificationTitle = intent .getStringExtra(NOTIFICATION_TITLE); String notificationMessage = intent .getStringExtra(NOTIFICATION_MESSAGE); String notificationUri = intent .getStringExtra(NOTIFICATION_URI); XNotificationService.this.notify(context, notificationId, notificationApiKey, notificationTitle, notificationMessage, notificationUri); } else if (ACTION_NOTIFICATION_CLICKED.equals(action)) { String notificationMessage = intent .getStringExtra(NOTIFICATION_MESSAGE); if (!isAppRunning(mPackageName)) { launchApp(mPackageName, notificationMessage); } else { XEvent evt = XEvent.createEvent( XEventType.PUSH_MSG_RECEIVED, notificationMessage); XSystemEventCenter.getInstance().sendEventAsync(evt); } } else if (ACTION_NOTIFICATION_CLEARED.endsWith(action)) { // TODO 用户点击清除通知 } } }; } } /** * 当网络改变的通知被触发后,执行的重连服务器或者断开的操作 */ private void genConnectionChangeBroadcastReceive() { if (null == mConnectivityReceiver) { mConnectivityReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { ConnectivityManager connectivityManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager .getActiveNetworkInfo(); if (networkInfo != null) { if (networkInfo.isConnected()) { connect(); } } else { disconnect(); } } }; } } /** * 加载raw下的push.properties文件的配置资源 * * @param context * 上下文 * @return 属性 */ private Properties openProperties(Context context) { Properties props = new Properties(); try { int id = context.getResources().getIdentifier(FILE_NAME, FILE_DIRECTORY, context.getPackageName()); props.load(context.getResources().openRawResource(id)); } catch (Exception e) { e.getMessage(); } return props; } @Override public void onDestroy() { unregisterNotificationReceiver(); unregisterConnectivityReceiver(); mConnectionManager.disconnect(); } /** * 连接服务器 */ public void connect() { mConnectionManager.connect(); } /** * 与服务器断开连接 */ public void disconnect() { mConnectionManager.disconnect(); } /** * 注册通知广播 */ private void registerNotificationReceiver() { if (null == mNotificationReceiver) { genNotificationReceiveBroadcastReceive(); } IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_SHOW_NOTIFICATION); filter.addAction(ACTION_NOTIFICATION_CLEARED); filter.addAction(ACTION_NOTIFICATION_CLICKED); registerReceiver(mNotificationReceiver, filter); } /** * 卸载通知广播 */ private void unregisterNotificationReceiver() { unregisterReceiver(mNotificationReceiver); } /** * 注册电话状态改变的广播 */ private void registerConnectivityReceiver() { genConnectionChangeBroadcastReceive(); genPhoneStateListener(); mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); IntentFilter filter = new IntentFilter(); filter.addAction(android.net.ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mConnectivityReceiver, filter); } /** * 卸载电话状态改变的广播监听 */ private void unregisterConnectivityReceiver() { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); unregisterReceiver(mConnectivityReceiver); } /** * 获取连接服务器的主机地址 * * @return 主机地址 */ public String getHost() { if(null != mHost) { return mHost; } String host = mProps.getProperty(HOST, ""); return host; } /** * 获取连接服务器的端口号 * * @return 端口号 */ public String getPort() { if(null != mPort) { return mPort; } String port = mProps.getProperty(PORT, ""); return port; } @Override public IBinder onBind(Intent intent) { return null; } /** * 从配置文件上面读取是否开启push * * @param context * 上下文 * @return true:启动push,false:不启动push */ public boolean isOpenPush(Context context) { Properties props = openProperties(context); return new Boolean(props.getProperty(IS_OPEN_PUSH, "")).booleanValue(); } /** * 显示通知 * * @param notificationId * 通知的id号 * @param apiKey * 通知的apiKey * @param title * 通知的标题 * @param message * 通知的内容 * @param uri * 传递的uri */ private void notify(Context context, String notificationId, String apiKey, String title, String message, String uri) { Notification notification = new Notification(); // 设置通知的各种属性 notification.icon = R.drawable.xface_logo; notification.defaults = Notification.DEFAULT_LIGHTS; notification.defaults |= Notification.DEFAULT_SOUND; notification.defaults |= Notification.DEFAULT_VIBRATE; notification.flags |= Notification.FLAG_AUTO_CANCEL; notification.when = System.currentTimeMillis(); notification.tickerText = message; // 点击通知 Intent clickIntent = new Intent(ACTION_NOTIFICATION_CLICKED); clickIntent.putExtra(NOTIFICATION_ID, notificationId); clickIntent.putExtra(NOTIFICATION_API_KEY, apiKey); clickIntent.putExtra(NOTIFICATION_TITLE, title); clickIntent.putExtra(NOTIFICATION_MESSAGE, message); clickIntent.putExtra(NOTIFICATION_URI, uri); PendingIntent clickPendingIntent = PendingIntent.getBroadcast(context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); notification.setLatestEventInfo(context, title, message, clickPendingIntent); // 清除通知 Intent clearIntent = new Intent(ACTION_NOTIFICATION_CLEARED); clearIntent.putExtra(NOTIFICATION_ID, notificationId); clearIntent.putExtra(NOTIFICATION_API_KEY, apiKey); PendingIntent clearPendingIntent = PendingIntent.getBroadcast(context, 0, clearIntent, 0); notification.deleteIntent = clearPendingIntent; Random random = new Random(System.currentTimeMillis()); mNotificationManager.notify(random.nextInt(), notification); } /** * 初始化对收到从服务器发过来通知请求的监听,主要实现获取服务器发过来的通知显示的信息以及发送通知广播 */ private void genNotificationPacketListener() { if (null == mNotificationPacketListener) { mNotificationPacketListener = new PacketListener() { @Override public void processPacket(Packet packet) { if (packet instanceof NotificationIQ) { NotificationIQ notification = (NotificationIQ) packet; String notificationId = notification.getId(); String notificationApiKey = notification.getApiKey(); String notificationTitle = notification.getTitle(); String notificationMessage = notification.getMessage(); String notificationUri = notification.getUri(); Intent intent = new Intent(ACTION_SHOW_NOTIFICATION); intent.putExtra(NOTIFICATION_ID, notificationId); intent.putExtra(NOTIFICATION_API_KEY, notificationApiKey); intent.putExtra(NOTIFICATION_TITLE, notificationTitle); intent.putExtra(NOTIFICATION_MESSAGE, notificationMessage); intent.putExtra(NOTIFICATION_URI, notificationUri); sendBroadcast(intent); } } }; } } /** * 获取服务器发过来通知请求的监听 * * @return 通知请求监听 */ public PacketListener getNotificationPacketListener() { genNotificationPacketListener(); return mNotificationPacketListener; } /** * 初始化扩展context */ public void setExtensionContext(XExtensionContext extensionContext) { } /** * 判断程序是否在运行(也就是说程序是否位于栈顶) * * @param packageName * 包名 * @return true:程序正在运行,false:程序没有运行 */ private boolean isAppRunning(String packageName) { ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> tasksInfo = activityManager.getRunningTasks(100); if (tasksInfo.size() > 0) { // 应用程序位于堆栈的顶层 if (packageName.equals(tasksInfo.get(0).topActivity .getPackageName())) { return true; } } return false; } /** * 启动程序,并将收到的通知内容传递的参数给程序 * * @param packageName * 包名 * @param appParamenter * 通知内容的参数 */ private void launchApp(String packageName, String appParamenter) { if (null == packageName) { return; } PackageInfo pi = null; try { pi = getPackageManager().getPackageInfo(packageName, 0); Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null); resolveIntent.setPackage(pi.packageName); PackageManager pm = getPackageManager(); List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0); if (null == apps || null == apps.iterator().next()) { return; } ResolveInfo ri = apps.iterator().next(); if (null == ri) { return; } String className = ri.activityInfo.name; Intent intent = new Intent(Intent.ACTION_MAIN); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); ComponentName cn = new ComponentName(packageName, className); intent.setComponent(cn); intent.putExtra(XConstant.TAG_APP_START_PARAMS, appParamenter); startActivity(intent); } catch (NameNotFoundException e) { } } }