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 及service:
<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>
导入jar包:asmack.jar,并将androidpn-client项目src的代码导成androidpn-client.jar,一起放入。
4. 由于项目需要,androidpn-client新增的一个回调的功能,回调的接口ConnectCallBack:
package com.linewell.pn;
/**
* 连接成功之后的回调函数
*
* @author zzhan@linewell.com
* @since 2014-5-26
*/
public interface ConnectCallBack {
/**
* 连接成功后执行事件
* @param username
*/
void doSuccess(String username);
}
同时,ServiceManager.java中新增加两个成员变量 :
//add by zzhan@linewell.com 连接成功之后的回调函数
public static ConnectCallBack conectCallBack;
//add by zzhan@linewell.com 用户自定义的通知对象
public static Notifier notifier;
修改XmppManager.java中的代码,在439行之后加入:
//mdf by zzhan@linewell.com
//每次连接成功后执行连接成功的回调函数
ConnectCallBack callback = ServiceManager.conectCallBack;
Log.i("Androidpn-Genius", "callbackUsername="+callbackUsername);
if(callback != null){
callback.doSuccess(callbackUsername);
}
5. 在自己的android app中,src新建消息通知对象Notifier.java,替换androidpn-client项目中对应的Notifier.java。
/*
* 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 (devnoh@gmail.com)
*/
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.
}
重写onResume方法:
/**
* 窗口恢复的事件
* add by cjq on 2014-08-11
*/
public void onResume() {
super.onResume();
// 通知点击后的处理
pushManager();
}
添加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 推送
}
其中JavaScriptManager.java:
package com.linewell.wellapp.utils;
import org.apache.cordova.CordovaWebView;
import android.content.Context;
import android.os.Handler;
/**
* android调用js处理逻辑
* @author cjianquan@linewell.com
*
* @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!");
}
}
}
其中startService()这个方法为启动连接到androidpn服务端的行为。
doSuccess()方法为成功获取管道ID后相应的业务处理。