1. 网上下载androidpn服务端Androidpn项目,在本地搭建并运行起来。
其中有几处配置文件需要根据情况修改:
resources目录 下:jdbc.properties修改对应的数据库连接。
2. 下载androidpn-client项目,修改res/raw/androidpn.properties
将xmppHost的值改为androidpn服务器的地址。
重命名lib-->libs,Build Path 重新修改引用jar的路径。
3.将android-client整合进自己的android app中:
修改文件AndroidManifest.xml:
新增权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<activity android:name="org.androidpn.client.NotificationDetailsActivity" android:label="Notification Details"> </activity> <activity android:name="org.androidpn.client.NotificationSettingsActivity" android:label="Notification Settings"> </activity> <service android:enabled="true" android:name="org.androidpn.client.NotificationService" android:label="NotificationService"> <intent-filter> <action android:name="org.androidpn.client.NotificationService" /> </intent-filter> </service>
4. 由于项目需要,androidpn-client新增的一个回调的功能,回调的接口ConnectCallBack:
package com.linewell.pn; /** * 连接成功之后的回调函数 * * @author [email protected] * @since 2014-5-26 */ public interface ConnectCallBack { /** * 连接成功后执行事件 * @param username */ void doSuccess(String username); }
//add by [email protected] 连接成功之后的回调函数 public static ConnectCallBack conectCallBack; //add by [email protected] 用户自定义的通知对象 public static Notifier notifier;
//mdf by [email protected] //每次连接成功后执行连接成功的回调函数 ConnectCallBack callback = ServiceManager.conectCallBack; Log.i("Androidpn-Genius", "callbackUsername="+callbackUsername); if(callback != null){ callback.doSuccess(callbackUsername); }
/* * Copyright (C) 2010 Moduad Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.androidpn.client; import java.util.Random; import com.linewell.wellapp.main.MainActivity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.util.Log; import android.widget.Toast; /** * This class is to notify the user of messages with NotificationManager. * * @author Sehwan Noh ([email protected]) */ public class Notifier { private static final String LOGTAG = LogUtil.makeLogTag(Notifier.class); private static final Random random = new Random(System.currentTimeMillis()); private Context context; private SharedPreferences sharedPrefs; private NotificationManager notificationManager; public Notifier(Context context) { this.context = context; this.sharedPrefs = context.getSharedPreferences( Constants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); this.notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); } public void notify(String notificationId, String apiKey, String title, String message, String uri) { Log.d(LOGTAG, "notify()..."); Log.d(LOGTAG, "notificationId=" + notificationId); Log.d(LOGTAG, "notificationApiKey=" + apiKey); Log.d(LOGTAG, "notificationTitle=" + title); Log.d(LOGTAG, "notificationMessage=" + message); Log.d(LOGTAG, "notificationUri=" + uri); if (isNotificationEnabled()) { // Show the toast if (isNotificationToastEnabled()) { Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } // Notification Notification notification = new Notification(); notification.icon = getNotificationIcon(); notification.defaults = Notification.DEFAULT_LIGHTS; if (isNotificationSoundEnabled()) { notification.defaults |= Notification.DEFAULT_SOUND; } if (isNotificationVibrateEnabled()) { notification.defaults |= Notification.DEFAULT_VIBRATE; } notification.flags |= Notification.FLAG_AUTO_CANCEL; notification.when = System.currentTimeMillis(); notification.tickerText = message; // Intent intent; // if (uri != null // && uri.length() > 0 // && (uri.startsWith("http:") || uri.startsWith("https:") // || uri.startsWith("tel:") || uri.startsWith("geo:"))) { // intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); // } else { // String callbackActivityPackageName = sharedPrefs.getString( // Constants.CALLBACK_ACTIVITY_PACKAGE_NAME, ""); // String callbackActivityClassName = sharedPrefs.getString( // Constants.CALLBACK_ACTIVITY_CLASS_NAME, ""); // intent = new Intent().setClassName(callbackActivityPackageName, // callbackActivityClassName); // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // } Intent intent = new Intent(context,MainActivity.class); intent.putExtra(Constants.NOTIFICATION_ID, notificationId); intent.putExtra(Constants.NOTIFICATION_API_KEY, apiKey); intent.putExtra(Constants.NOTIFICATION_TITLE, title); intent.putExtra(Constants.NOTIFICATION_MESSAGE, message); intent.putExtra(Constants.NOTIFICATION_URI, uri); intent.putExtra("isPush", true); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); notification.setLatestEventInfo(context, title, message, contentIntent); notificationManager.notify(random.nextInt(), notification); // Intent clickIntent = new Intent( // Constants.ACTION_NOTIFICATION_CLICKED); // clickIntent.putExtra(Constants.NOTIFICATION_ID, notificationId); // clickIntent.putExtra(Constants.NOTIFICATION_API_KEY, apiKey); // clickIntent.putExtra(Constants.NOTIFICATION_TITLE, title); // clickIntent.putExtra(Constants.NOTIFICATION_MESSAGE, message); // clickIntent.putExtra(Constants.NOTIFICATION_URI, uri); // // positiveIntent.setData(Uri.parse((new StringBuilder( // // "notif://notification.adroidpn.org/")).append(apiKey).append( // // "/").append(System.currentTimeMillis()).toString())); // PendingIntent clickPendingIntent = PendingIntent.getBroadcast( // context, 0, clickIntent, 0); // // notification.setLatestEventInfo(context, title, message, // clickPendingIntent); // // Intent clearIntent = new Intent( // Constants.ACTION_NOTIFICATION_CLEARED); // clearIntent.putExtra(Constants.NOTIFICATION_ID, notificationId); // clearIntent.putExtra(Constants.NOTIFICATION_API_KEY, apiKey); // // negativeIntent.setData(Uri.parse((new StringBuilder( // // "notif://notification.adroidpn.org/")).append(apiKey).append( // // "/").append(System.currentTimeMillis()).toString())); // PendingIntent clearPendingIntent = PendingIntent.getBroadcast( // context, 0, clearIntent, 0); // notification.deleteIntent = clearPendingIntent; // // notificationManager.notify(random.nextInt(), notification); } else { Log.w(LOGTAG, "Notificaitons disabled."); } } private int getNotificationIcon() { return sharedPrefs.getInt(Constants.NOTIFICATION_ICON, 0); } private boolean isNotificationEnabled() { return sharedPrefs.getBoolean(Constants.SETTINGS_NOTIFICATION_ENABLED, true); } private boolean isNotificationSoundEnabled() { return sharedPrefs.getBoolean(Constants.SETTINGS_SOUND_ENABLED, true); } private boolean isNotificationVibrateEnabled() { return sharedPrefs.getBoolean(Constants.SETTINGS_VIBRATE_ENABLED, true); } private boolean isNotificationToastEnabled() { return sharedPrefs.getBoolean(Constants.SETTINGS_TOAST_ENABLED, false); } }
其中103代码:
Intent intent = new Intent(context,MainActivity.class);表示 点击通知消息时跳转到的下一下activity 为MainActivity。
补充说明:110行代码: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 必须这样设置,
同时,AndroidManifest.xml中,
同时,在MainActivity中重写onNewIntent方法:
/** * singleTask模式,启动该activity需要重置intent,因此重写该方法 * add by cjq on 2014-08-11 */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); Log.e("life", "onNewIntent"); //here we can use getIntent() to get the extra data. }
/** * 窗口恢复的事件 * add by cjq on 2014-08-11 */ public void onResume() { super.onResume(); // 通知点击后的处理 pushManager(); }
/** * 只有通知栏的才要进行处理 * add by cjq on 2014-08-11 */ private void pushManager() { Intent intent = getIntent(); // .getExtras()得到intent所附带的额外数据 Bundle bundle = intent.getExtras(); // 是否是推送通知 boolean isPush = bundle.getBoolean("isPush"); // 只有是推送时,才会触发 if (isPush) { String notificationId = bundle.getString(org.androidpn.client.Constants.NOTIFICATION_ID); String title = bundle.getString(org.androidpn.client.Constants.NOTIFICATION_TITLE); String message = bundle.getString(org.androidpn.client.Constants.NOTIFICATION_MESSAGE); String uri = bundle.getString(org.androidpn.client.Constants.NOTIFICATION_URI); String splitStr[] = uri.split(":"); String messageId = ""; if (splitStr != null && splitStr.length > 0) { uri = splitStr[1]; messageId = splitStr[0]; } SharedPreferencesUtils.save(this, "NOTIFICATION_ID", notificationId); SharedPreferencesUtils.save(this, "NOTIFICATION_TITLE", title); SharedPreferencesUtils.save(this, "NOTIFICATION_MESSAGE", message); SharedPreferencesUtils.save(this, "NOTIFICATION_URI", uri); SharedPreferencesUtils.save(this, "NOTIFICATION_MSGID", messageId); new JavaScriptManager(this).openInfoPage(handler, webView, isPush); // 重新设为false intent.putExtra("isPush", false); }// end if 推送 }
package com.linewell.wellapp.utils; import org.apache.cordova.CordovaWebView; import android.content.Context; import android.os.Handler; /** * android调用js处理逻辑 * @author [email protected] * * @sine 2014-8-11 */ public class JavaScriptManager { Context mContext; public JavaScriptManager(Context c) { mContext = c; } /** * 打开待办事项列表 * @param handler Handler处理对象 * @param webView CordovaWebView 对象 * @param isPush 是否是推送 */ public void openInfoPage(Handler handler, final CordovaWebView webView, final boolean isPush) { handler.post(new Runnable() { @Override public void run() { // 调用js脚本 webView.loadUrl("javascript:openInfoPage('"+ isPush +"')"); } }); } }
6. android app 端启动服务,启动的动作放在PushNotificationPlugin.java类中处理,此类实现回调接口:
package org.apache.cordova; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import java.util.Map; import org.androidpn.client.ServiceManager; import org.apache.cordova.api.Plugin; import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult.Status; import org.json.JSONArray; import org.json.JSONObject; import android.util.Log; import com.linewell.pn.ConnectCallBack; import com.linewell.wellapp.main.R; import com.linewell.wellapp.utils.SharedPreferencesUtils; public class PushNotificationPlugin extends Plugin implements ConnectCallBack{ private static final String ACTION_NOTIFICATION = "notification"; private static final String ACTION_GETSHAREDATA = "getsharedata"; // private static final String ACTION_TIME = "time"; JSONObject userChoice = new JSONObject(); private String loginName = ""; private String urlStr = ""; @Override public PluginResult execute(final String action, final JSONArray data, final String callBackId) { Log.d("PushNotificationPlugin", "Plugin Called"); PluginResult result = null; try { if (ACTION_NOTIFICATION.equalsIgnoreCase(action)) { loginName = data.getString(0); urlStr = data.getString(1); Log.d("PushNotificationPlugin execute", ACTION_NOTIFICATION); this.startService(); // this.success(userChoice, callBackId); final PluginResult r = new PluginResult(PluginResult.Status.OK, userChoice); r.setKeepCallback(true); return r; }else if(ACTION_GETSHAREDATA.equals(action)){ String notificationId = (String)SharedPreferencesUtils.get(this.cordova.getActivity(), "NOTIFICATION_ID", ""); String title = (String)SharedPreferencesUtils.get(this.cordova.getActivity(), "NOTIFICATION_TITLE", ""); String message = (String)SharedPreferencesUtils.get(this.cordova.getActivity(), "NOTIFICATION_TITLE", ""); String uri = (String)SharedPreferencesUtils.get(this.cordova.getActivity(), "NOTIFICATION_URI", ""); String messageId = (String)SharedPreferencesUtils.get(this.cordova.getActivity(), "NOTIFICATION_MSGID", ""); userChoice.put("notificationId", notificationId); userChoice.put("title", title); userChoice.put("message", message); userChoice.put("uri", uri); userChoice.put("messageId", messageId); final PluginResult r = new PluginResult(PluginResult.Status.OK, userChoice); r.setKeepCallback(true); return r; }else { result = new PluginResult(Status.INVALID_ACTION); Log.d("PushNotificationPlugin", "Invalid action : " + action + " passed"); } }catch(Exception e){ } return result; } public void startService(){ ServiceManager serviceManager = new ServiceManager(this.cordova.getActivity()); ServiceManager.conectCallBack = this; try{ serviceManager.setNotificationIcon(R.drawable.ic_launcher); serviceManager.startService(); }catch(Exception e){ Log.e("Error",e.getMessage() ); } } @Override public void doSuccess(String username) { try { userChoice.put("username", username); saveOrUpdateChannel(username,loginName,urlStr); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 保存或更新用户与管道ID的关联关系 * @param username 此处指管道ID * @param loginName * @param urlStr */ public void saveOrUpdateChannel(String username,String loginName,String urlStr) throws Exception{ // String url = urlStr+"&loginName="+loginName+"&username="+username; // httpGet(url); // loginName = URLEncoder.encode(loginName,"GB2312"); URL url = new URL(urlStr+"loginName="+loginName+"&username="+username); HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 基于HTTP协议的连接对象 conn.setConnectTimeout(5000);// 请求超时时间 5s conn.setRequestMethod("GET");// 请求方式 Map<String,List<String>> map = conn.getHeaderFields(); for(String key:map.keySet()){ System.out.println(key+"-->>"+map.get(key)); } if(conn.getResponseCode()==200){ Log.i("wellApp", "save success!"); } } }
doSuccess()方法为成功获取管道ID后相应的业务处理。