1. 程式人生 > >AndroidStudio離線打包MUI集成JPush極光推送並在java後端管理推送

AndroidStudio離線打包MUI集成JPush極光推送並在java後端管理推送

覆蓋 如果 dep record tco mat resource 靜態 pkg

1.AndroidStudio離線打包MUI

  如何離線打包請參看上篇隨筆《AndroidStudio離線打包MUI》

2.集成極光推送

  官方文檔:https://docs.jiguang.cn/jpush/client/Android/android_guide/

  建議采用 jcenter 自動集成 的方式,手動集成對新手來說容易出錯

  使用jcenter自動集成的開發者,不需要在項目中添加jar和so,jcenter會自動完成依賴;在AndroidManifest.xml中不需要添加任何JPush SDK 相關的配置,jcenter會自動導入。

  • 如果開發者需要修改組件屬性,可以在本地的 AndroidManifest 中定義同名的組件並配置想要的屬性,然後用 xmlns:tools 來控制本地組件覆蓋 jcenter 上的組件。示例:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.tests.flavorlib.app"
        xmlns:tools="http://schemas.android.com/tools">
    
        <application
            android:icon="@drawable/icon"
            android:name="com.example.jpushdemo.ExampleApplication"
            android:label="@string/app_name" >
    
            <service android:name="cn.jpush.android.service.PushService"
                android:process=":multiprocess"
                tools:node="replace" >
    
                ……
            </service>
    
        ……
      </application>
    
      ……
    </manifest>
    
  • 確認android studio的 Project 根目錄的主 gradle 中配置了jcenter支持。(新建project默認配置就支持)

    buildscript {
        repositories {
            jcenter()
        }
        ......
    }
    
    allprojets {
        repositories {
            jcenter()
        }
    }
  • 在 module 的 gradle 中添加依賴和AndroidManifest的替換變量。

    android {
        ......
        defaultConfig {
            applicationId "com.xxx.xxx" //JPush上註冊的包名.
            ......
    
            ndk {
                //選擇要添加的對應cpu類型的.so庫。
                abiFilters ‘armeabi‘, ‘armeabi-v7a‘, ‘arm64-v8a‘
                // 還可以添加 ‘x86‘, ‘x86_64‘, ‘mips‘, ‘mips64‘
            }
    
            manifestPlaceholders = [
                JPUSH_PKGNAME : applicationId,
                JPUSH_APPKEY : "你的appkey", //JPush上註冊的包名對應的appkey.
                JPUSH_CHANNEL : "developer-default", //暫時填寫默認值即可.
            ]
            ......
        }
        ......
    }
    
    dependencies {
        ......
    
        compile ‘cn.jiguang.sdk:jpush:3.1.1‘  // 此處以JPush 3.1.1 版本為例。
        compile ‘cn.jiguang.sdk:jcore:1.1.9‘  // 此處以JCore 1.1.9 版本為例。
        ......
    }
    

3.Android項目中增加註冊、獲取極光推送相關信息的代碼

  3.1.在AS中增加JPushUtil工具類

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.widget.Toast;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.jpush.android.api.JPushInterface;
import io.dcloud.common.adapter.util.Logger;

public class JpushUtil {
    public static final String PREFS_NAME = "JPUSH_EXAMPLE";
    public static final String PREFS_DAYS = "JPUSH_EXAMPLE_DAYS";
    public static final String PREFS_START_TIME = "PREFS_START_TIME";
    public static final String PREFS_END_TIME = "PREFS_END_TIME";
    public static final String KEY_APP_KEY = "JPUSH_APPKEY";

    public static boolean isEmpty(String s) {
        if (null == s)
            return true;
        if (s.length() == 0)
            return true;
        if (s.trim().length() == 0)
            return true;
        return false;
    }
    /**
     * 只能以 “+” 或者 數字開頭;後面的內容只能包含 “-” 和 數字。
     * */
    private final static String MOBILE_NUMBER_CHARS = "^[+0-9][-0-9]{1,}$";
    public static boolean isValidMobileNumber(String s) {
        if(TextUtils.isEmpty(s)) return true;
        Pattern p = Pattern.compile(MOBILE_NUMBER_CHARS);
        Matcher m = p.matcher(s);
        return m.matches();
    }
    // 校驗Tag Alias 只能是數字,英文字母和中文
    public static boolean isValidTagAndAlias(String s) {
        Pattern p = Pattern.compile("^[\u4E00-\u9FA50-9a-zA-Z_!@#$&*+=.|]+$");
        Matcher m = p.matcher(s);
        return m.matches();
    }

    // 取得AppKey
    public static String getAppKey(Context context) {
        Bundle metaData = null;
        String appKey = null;
        try {
            ApplicationInfo ai = context.getPackageManager().getApplicationInfo(
                    context.getPackageName(), PackageManager.GET_META_DATA);
            if (null != ai)
                metaData = ai.metaData;
            if (null != metaData) {
                appKey = metaData.getString(KEY_APP_KEY);
                if ((null == appKey) || appKey.length() != 24) {
                    appKey = null;
                }
            }
        } catch (NameNotFoundException e) {

        }
        return appKey;
    }
    
    // 取得版本號
    public static String GetVersion(Context context) {
		try {
			PackageInfo manager = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			return manager.versionName;
		} catch (NameNotFoundException e) {
			return "Unknown";
		}
	}

    public static void showToast(final String toast, final Context context)
    {
    	new Thread(new Runnable() {
			
			@Override
			public void run() {
				Looper.prepare();
				Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
				Looper.loop();
			}
		}).start();
    }
    
    public static boolean isConnected(Context context) {
        ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = conn.getActiveNetworkInfo();
        return (info != null && info.isConnected());
    }
    
	public static String getImei(Context context, String imei) {
        String ret = null;
		try {
			TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            ret = telephonyManager.getDeviceId();
		} catch (Exception e) {
			Logger.e(JpushUtil.class.getSimpleName(), e.getMessage());
		}
		if (isReadableASCII(ret)){
            return ret;
        } else {
            return imei;
        }
	}

    private static boolean isReadableASCII(CharSequence string){
        if (TextUtils.isEmpty(string)) return false;
        try {
            Pattern p = Pattern.compile("[\\x20-\\x7E]+");
            return p.matcher(string).matches();
        } catch (Throwable e){
            return true;
        }
    }

    public static String getDeviceId(Context context) {
        return JPushInterface.getUdid(context);
    }
}

  

  3.2.增加JPushInitActivity類

import android.os.Bundle;

import cn.jpush.android.api.InstrumentedActivity;
import cn.jpush.android.api.JPushInterface;

/**
 * 初始化極光推送的相關信息
 */
public class JPushInitActivity extends InstrumentedActivity {

	public static String APP_KEY = "";//在極光推送中註冊的應用ID
	public static String MASTER_SECRET  = "08123213666d973dkkik3bbe7fd6";//在極光推送官網註冊後獲得的密碼(請改為你自己註冊後的值)
	public static String REGISTRATION_ID = "";//安裝APP的用戶在極光推送中註冊的ID

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		init();
	}
	public void init(){
		JPushInterface.init(getApplicationContext());
		//獲取初始化之後的環境
		APP_KEY = JpushUtil.getAppKey(getApplicationContext());
		REGISTRATION_ID = JPushInterface.getRegistrationID(getApplicationContext());
	}

	public static String getJPushData(){
		return "appKey:"+APP_KEY+";masterSecret:"+MASTER_SECRET+";registrationId:"+REGISTRATION_ID;
	}

}

  

  3.3.在AndroidManifest.xml中註冊JPushInitActivity

 <!-- 用於初始化極光推送的註冊數據,不顯示給用戶  -->
        <activity
            android:name=".jpush.JPushInitActivity"
            android:theme="@android:style/Theme.NoDisplay">
        </activity>

  

  3.4.在mui.js中創建Activity並完成註冊

mui.plusReady(function() {
	//調用原生Activity
	var Intent = plus.android.importClass("android.content.Intent");
	// 獲取主Activity對象的實例
	var main = plus.android.runtimeMainActivity();
	// 創建Intent
	var naviIntent = new Intent();
	var ComponentName = plus.android.importClass("android.content.ComponentName");
	//創建極光推送註冊Activity,包名請換成你自己的包名
	naviIntent.setComponent(new ComponentName(main, "com.xxx.xxx.xxx.JPushInitActivity"));
	main.startActivity(naviIntent);

	 //調用java方法
	$(".login_btn").click(function(){
		//引入java類文件,包名請換成你自己的包名
		var jPush  = plus.android.importClass("com.xxx.xxx.xxx.JPushInitActivity");
		//調用靜態方法
		var jPushData = jPush.getJPushData();
		//輸出返回值
		alert(jPushData);
		//TODO 在登錄時將jPushData及用戶名、密碼一並傳給java後端
          //...... }) })

  

4.java端代碼

  4.1 接收登錄信息,將registrationId與用戶綁定,請根據自己的業務去進行關聯

                   //驗證成功,將jPushId與用戶關聯起來
				try {
					String[] split = jPushData.split(";");
					for (String str : split) {
						if ("registrationId".equals(str.split(":")[0])) {
							String jPushId = str.split(":")[1];
							String sql = "UPDATE BO_PBS_ORG_EXT_USER SET J_PUSH_ID = ? WHERE YHZH = ?";
							Object[] params = { jPushId, loginUserModel.getUSER_ACCOUNT() };
							db.update(sql, params);
							break;
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

 

  4.2 新增service接口JpushMessageService

public interface JpushMessageService {

	/**
	 * 發送給所有用戶
	 * @param content
	 * @return
	 */
	public String sendPushAll(String content);

	/**
	 * 發送給userId對應的用戶
	 * @param userId
	 * @param content
	 * @return
	 */
	public String senPushByUserId(String userId, String content);

}

  

  4. 3 新增service接口實現類JpushMessageServiceImpl

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.pbs.mobile.business.service.JpushMessageService;
import com.pbs.mobile.util.JPushUtil;
import com.pbs.mobile.util.ReturnUtil;
import com.pbs.workflow.service.DataBaseService;
import com.pbs.workflow.service.UserService;

import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.PushPayload;

@Service
public class JpushMessageServiceImpl implements JpushMessageService {

	@Resource
	UserService userService;

	@Resource
	DataBaseService db;

	private final static String appKey = "weqwewe1123123123123";//這裏請填寫自己註冊獲得的值,或者通過mui向後臺傳值

	private final static String masterSecret = "213123123asdjfoi1293";//這裏請填寫自己註冊獲得的值,或者通過mui向後臺傳值
	/**
	 * 保存離線的時長。秒為單位。最多支持10天(864000秒)。 0 表示該消息不保存離線。即:用戶在線馬上發出,當前不在線用戶將不會收到此消息。
	 * 此參數不設置則表示默認,默認為保存1天的離線消息(86400秒)。
	 */
	private static long timeToLive = 60 * 60 * 24;

	private static JPushClient jPushClient = null;

	private static final Logger logger = Logger.getLogger(JpushMessageServiceImpl.class);

	@Override
	public String sendPushAll(String content) {
		ClientConfig config = ClientConfig.getInstance();
		config.setMaxRetryTimes(5);
		config.setConnectionTimeout(10 * 1000);
		config.setGlobalPushSetting(false, timeToLive);
		jPushClient = new JPushClient(masterSecret, appKey, null, config);
		boolean flag = false;
		try {
			PushPayload payload = JPushUtil.buildPushObject_all_all_alert(content);
			PushResult result = jPushClient.sendPush(payload);
			if (null != result) {
				logger.info("Get resul ---" + result);
				flag = true;
			}
		} catch (APIConnectionException e) {
			logger.error("Connection error. Should retry later. ", e);
		} catch (APIRequestException e) {
			logger.error("Error response from JPush server. Should review and fix it. ", e);
			logger.info("HTTP Status: " + e.getStatus());
			logger.info("Error Code: " + e.getErrorCode());
			logger.info("Error Message: " + e.getErrorMessage());
			logger.info("Msg ID: " + e.getMsgId());
		}
		Map<String, Object> result = new HashMap<String, Object>();
		if (flag) {
			result.put("status", "ok");
			result.put("code", "0");
			result.put("msg", "發送成功");
		} else {
			result.put("status", "fail");
			result.put("code", "-1");
			result.put("msg", "發送失敗");
		}
		return ReturnUtil.getJsonStr(result);
	}

	@Override
	public String senPushByUserId(String userId, String content) {
		boolean flag = false;
		try {
			//在數據庫中查詢極光推送註冊信息以及是否接受推送(可以根據自己業務省略是否接收推送的判斷)
              //eu.J_PUSH_ID就是我們在登錄之後跟用戶管理起來的registrationId
			String sql = "SELECT eu.J_PUSH_ID,eu.ACCEPT_PUSH FROM PBS_ORG_USER u JOIN BO_PBS_ORG_EXT_USER eu ON u.USER_ACCOUNT = eu.YHZH AND u.ID = ?";
			Object[] params = { userId };
			List<Map<String, Object>> records = db.queryList(sql, params);
			if (records != null && records.size() > 0) {
				Boolean acceptPush = records.get(0).get("ACCEPT_PUSH") == null ? true : (boolean) records.get(0).get("ACCEPT_PUSH");
				String jPushId = records.get(0).get("J_PUSH_ID") == null ? "" : (String) records.get(0).get("J_PUSH_ID");
				if (acceptPush && StringUtils.isNotEmpty(jPushId)) {
					JPushClient jPushClient = new JPushClient(masterSecret, appKey);
					List<String> regeSterIds = new ArrayList<>();
					regeSterIds.add(jPushId);
					try {
						PushPayload payload = JPushUtil.buildPushObject_all_all_regesterIds(regeSterIds, content);
						PushResult pushResult = jPushClient.sendPush(payload);
						if (null != pushResult) {
							logger.info("Get result ----" + pushResult);
							flag = true;
						}
					} catch (APIConnectionException e) {
						logger.error("Connection error. Should retry later. ", e);
					} catch (APIRequestException e) {
						logger.error("Error response from JPush server. Should review and fix it. ", e);
						logger.info("HTTP Status: " + e.getStatus());
						logger.info("Error Code: " + e.getErrorCode());
						logger.info("Error Message: " + e.getErrorMessage());
						logger.info("Msg ID: " + e.getMsgId());
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		Map<String, Object> result = new HashMap<String, Object>();
		if (flag) {
			result.put("status", "ok");
			result.put("code", "0");
			result.put("msg", "發送成功");
		} else {
			result.put("status", "fail");
			result.put("code", "-1");
			result.put("msg", "發送失敗");
		}
		return ReturnUtil.getJsonStr(result);
	}

}

  

AndroidStudio離線打包MUI集成JPush極光推送並在java後端管理推送