1. 程式人生 > >Android 整合華為推送 push

Android 整合華為推送 push

由於專案需要我們不得不對華為push進行研究。

按照國際慣例先百度一波,發現各個大牛都是對於華為push的填坑,很明顯,這個推送的問題還是有很多的。

這裡引用:Android整合華為推送踩坑問題總結

  1. 使用老版push還是新版push
  2. PushReceiver中的onEvent()回撥觸發問題
  3. APP接收到推送後,點選訊息,總是會先開啟啟動頁
  4. 如何自定義動作intent

如何解決請跳轉連結檢視詳細內容。


關於華為推送的注意點:

支援NC功能的手機:部分EMUI4.0和4.1的手機,以及EMUI5.0及之後的華為手機。 

是否接受通知欄訊息:當是中國大陸地區的華為手機,必須滿足EMUI版本不低於EMUI5.1
當是海外地區的華為手機或者非華為品牌手機,則必須滿足華為移動服務的版本不低於2.5.0

針對以上:

//判斷EMUI 大於 等於 12  相當於5.1
int emuiApiLevel = 0;            
        try {            
            Class cls = Class.forName("android.os.SystemProperties");            
            Method method = cls.getDeclaredMethod("get", new Class[]{String.class});            
            emuiApiLevel = Integer.parseInt((String) method.invoke(cls, new Object[]{"ro.build.hw_emui_api_level"}));            
        } catch (Exception e) {            
            e.printStackTrace();            
        }        

//判斷服務版本 大於等於 250  
PackageInfo pi = null;            
        PackageManager pm = context.getPackageManager();            
        int hwid = 0;            
        try {            
            pi = pm.getPackageInfo("com.huawei.hwid", 0);            
            if (pi != null) {            
                result = pi.versionCode;            
            }            
        } catch (PackageManager.NameNotFoundException e) {            
            e.printStackTrace();            
        }        

 

一、註冊華為開發者聯盟賬號 右上角進入管理中心

申請push服務 建立應用。

注意:

SHA256證書指紋1  此證書需要打包你的apk (放在根目錄 方便)然後在Terminal 中輸入

keytool -v -list -keystore  名稱.jks 

輸入密碼後 即可檢視

二、為了每次不用我們打包後安裝

File -> project Structure -> app -> Signing 新增我們建立的jks

-> Build Types -> debug ->Signing Config 選擇剛才建立的jks 就好。

有時候我們會忽略這一點 以至於 每次都會 6003  告訴我們 簽名有問題

大家注意一下就好。

三、開發整合

下載Sdk

HMS Agent套件  HMSAgent_2.6.1.302.zip

解壓後點擊 GetHMSAgent_cn.bat

按照提示 輸入相關內容 沒有 直接Enter 就好

然後找到copysrc資料夾 將java 資料夾中的所有內容 拷貝到你的專案裡

目錄請看下圖  com下  dak 是我專案的包名

然後放入 華為的Agent 套件  

注意: 目錄一定要相對應

然後把AppManifestConfig.xml 中內容 放入到AndroidManifest.xml 中。

有一個標紅點 需要放入一個Receiver 

我們把華為官方的simple中 HuaweiPushRevicer 拿過來就好了。

public class HuaweiPushRevicer extends PushReceiver {


    public static final String TAG = "HuaweiPushRevicer";

    public static final String ACTION_UPDATEUI = "action.updateUI";
    public static final String ACTION_TOKEN = "action.updateToken";

    private static List<IPushCallback> pushCallbacks = new ArrayList<IPushCallback>();
    private static final Object CALLBACK_LOCK = new Object();

    public interface IPushCallback {
        void onReceive(Intent intent);
    }

    public static void registerPushCallback(IPushCallback callback) {
        synchronized (CALLBACK_LOCK) {
            pushCallbacks.add(callback);
        }
    }

    public static void unRegisterPushCallback(IPushCallback callback) {
        synchronized (CALLBACK_LOCK) {
            pushCallbacks.remove(callback);
        }
    }

    @Override
    public void onToken(Context context, String tokenIn, Bundle extras) {
        Log.e("onToken:", tokenIn);

        String belongId = extras.getString("belongId");
        Intent intent = new Intent();
        intent.setAction(ACTION_TOKEN);
        intent.putExtra(ACTION_TOKEN, tokenIn);
        callBack(intent);

        intent = new Intent();
        intent.setAction(ACTION_UPDATEUI);
        intent.putExtra("log", "belongId is:" + belongId + " Token is:" + tokenIn);
        callBack(intent);
    }

    @Override
    public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {

        Log.e("onPushMsg:", "接收訊息");
        try {
            //CP可以自己解析訊息內容,然後做相應的處理 | CP can parse message content on its own, and then do the appropriate processing
            String content = new String(msg, "UTF-8");
            Intent intent = new Intent();
            intent.setAction(ACTION_UPDATEUI);
            intent.putExtra("log", "Receive a push pass message with the message:" + content);
            callBack(intent);
        } catch (Exception e) {
            Intent intent = new Intent();
            intent.setAction(ACTION_UPDATEUI);
            intent.putExtra("log", "Receive push pass message, exception:" + e.getMessage());
            callBack(intent);
        }
        return false;
    }

    public void onEvent(Context context, Event event, Bundle extras) {
        Log.e("onEvent:", "事件");
        Intent intent = new Intent();
        intent.setAction(ACTION_UPDATEUI);

        int notifyId = 0;
        if (Event.NOTIFICATION_OPENED.equals(event) || Event.NOTIFICATION_CLICK_BTN.equals(event)) {
            notifyId = extras.getInt(BOUND_KEY.pushNotifyId, 0);
            if (0 != notifyId) {
                NotificationManager manager = (NotificationManager) context
                        .getSystemService(Context.NOTIFICATION_SERVICE);
                manager.cancel(notifyId);
            }
        }

        String message = extras.getString(BOUND_KEY.pushMsgKey);
        intent.putExtra("log", "Received event,notifyId:" + notifyId + " msg:" + message);
        callBack(intent);
        super.onEvent(context, event, extras);
    }

    @Override
    public void onPushState(Context context, boolean pushState) {
        Log.e("onPushState:", "接收狀態");
        Intent intent = new Intent();
        intent.setAction(ACTION_UPDATEUI);
        intent.putExtra("log", "The Push connection status is:" + pushState);
        callBack(intent);
    }

    private static void callBack(Intent intent) {
        synchronized (CALLBACK_LOCK) {
            for (IPushCallback callback : pushCallbacks) {
                if (callback != null) {
                    callback.onReceive(intent);
                }
            }
        }
    }
}

注意不要混亂。

在project build.gradle 中新增  maven {url 'http://developer.huawei.com/repo/'}

在module build.gradle 中新增 如下

// 此處版本號僅為示例,請手動修改成實際整合的HMSSDK版本號

String HMSSDKVer ='2.6.1.301'

compile 'com.huawei.android.hms:iap:'+HMSSDKVer

compile 'com.huawei.android.hms:game:'+HMSSDKVer

compile 'com.huawei.android.hms:sns:'+HMSSDKVer

compile 'com.huawei.android.hms:hwid:'+HMSSDKVer

compile 'com.huawei.android.hms:push:'+HMSSDKVer

compile 'com.huawei.android.hms:opendevice:'+HMSSDKVer 

需要哪個新增哪個就好。 Sync Now 一下

檢視Agent 套件 是否還繼續報錯。

如果報錯 看下是否少添加了內容

值得一提:

resConfigs "en", "zh-rCN","其他應用需要支援的語言"

確認專案需求是否需要 。

四、程式碼內容

在Application 的 onCreate 中 初始化套件  

HMSAgent.init(this);

在第一個Activity 中連線  我在Main中

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity:";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        connectHMSAgent();


        Button button = findViewById(R.id.btn_push);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,PushActivity.class));
            }
        });
    }

    private void connectHMSAgent() {
        HMSAgent.connect(this, new ConnectHandler() {
            @Override
            public void onConnect(int rst) {
                Log.e("MainActivity:","HMS connect end:" + rst);
            }
        });
    }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.dak.administrator.hwpushsimple.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="跳轉push"
        android:id="@+id/btn_push"
        />

</LinearLayout>

 

以下是 官方simple 中測試 Activity  我只拿了 push 部份 可以用來測試

public class PushActivity extends AppCompatActivity implements HuaweiPushRevicer.IPushCallback, View.OnClickListener {

    private String token;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_push);

        Button btn = (Button) findViewById(R.id.btn_push);
        if (btn != null) {
            btn.setTextColor(Color.RED);
            btn.setEnabled(false);
        }

        findViewById(R.id.btn_gettoken).setOnClickListener(this);
        findViewById(R.id.btn_deletetoken).setOnClickListener(this);
        findViewById(R.id.btn_getpushstatus).setOnClickListener(this);
        findViewById(R.id.btn_setnormal).setOnClickListener(this);
        findViewById(R.id.btn_setnofify).setOnClickListener(this);
        findViewById(R.id.btn_agreement).setOnClickListener(this);

        registerBroadcast();
    }

    /**
     * 獲取token | get push token
     */
    private void getToken() {
        showLog("get token: begin");
        HMSAgent.Push.getToken(new GetTokenHandler() {
            @Override
            public void onResult(int rtnCode) {
                showLog("get token: end code=" + rtnCode);
            }
        });

    }

    /**
     * 刪除token | delete push token
     */
    private void deleteToken(){
        showLog("deleteToken:begin");
        HMSAgent.Push.deleteToken(token, new DeleteTokenHandler() {
            @Override
            public void onResult(int rst) {
                showLog("deleteToken:end code=" + rst);
            }
        });
    }

    /**
     * 獲取push狀態 | Get Push State
     */
    private void getPushStatus() {
        showLog("getPushState:begin");
        HMSAgent.Push.getPushState(new GetPushStateHandler() {
            @Override
            public void onResult(int rst) {
                showLog("getPushState:end code=" + rst);
            }
        });
    }

    /**
     * 設定是否接收普通透傳訊息 | Set whether to receive normal pass messages
     * @param enable 是否開啟 | enabled or not
     */
    private void setReceiveNormalMsg(boolean enable){
        showLog("enableReceiveNormalMsg:begin");
        HMSAgent.Push.enableReceiveNormalMsg(enable, new EnableReceiveNormalMsgHandler() {
            @Override
            public void onResult(int rst) {
                showLog("enableReceiveNormalMsg:end code=" + rst);
            }
        });
    }

    /**
     * 設定接收通知訊息 | Set up receive notification messages
     * 注意:當是中國大陸地區的華為手機,必須滿足EMUI版本不低於EMUI5.1
     * 當是海外地區的華為手機或者非華為品牌手機,則必須滿足華為移動服務的版本不低於2.5.0。
     * @param enable 是否開啟 | enabled or not
     */
    private void setReceiveNotifyMsg(boolean enable){
        showLog("enableReceiveNotifyMsg:begin");
        HMSAgent.Push.enableReceiveNotifyMsg(enable, new EnableReceiveNotifyMsgHandler() {
            @Override
            public void onResult(int rst) {
                showLog("enableReceiveNotifyMsg:end code=" + rst);
            }
        });
    }

    /**
     * 顯示push協議 | Show Push protocol
     */
    private void showAgreement(){
        showLog("queryAgreement:begin");
        HMSAgent.Push.queryAgreement(new QueryAgreementHandler() {
            @Override
            public void onResult(int rst) {
                showLog("queryAgreement:end code=" + rst);
            }
        });
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_push) {
            // 本頁面切換到本頁面的按鈕事件不處理 | "This page switches to itself" button event does not need to be handled
            return;
        } else {
            // 如果不是tab切換按鈕則處理業務按鈕事件 | Handle Business button events without the TAB toggle button
            switch (id) {
                case R.id.btn_gettoken:
                    getToken();
                    break;
                case R.id.btn_deletetoken:
                    deleteToken();
                    break;
                case R.id.btn_getpushstatus:
                    getPushStatus();
                    break;
                case R.id.btn_setnormal:
                    setReceiveNormalMsg(true);
                    break;
                case R.id.btn_setnofify:
                    setReceiveNotifyMsg(true);
                    break;
                case R.id.btn_agreement:
                    showAgreement();
                    break;
                default:
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        HuaweiPushRevicer.unRegisterPushCallback(this);;
    }

    /**
     * 以下程式碼為sample自身邏輯,和業務能力不相關
     * 作用僅僅為了在sample介面上顯示push相關資訊
     */
    private void registerBroadcast() {
        HuaweiPushRevicer.registerPushCallback(this);
    }

    @Override
    public void onReceive(Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            Bundle b = intent.getExtras();
            if (b != null && ACTION_TOKEN.equals(action)) {
                token = b.getString(ACTION_TOKEN);
            } else if (b != null && ACTION_UPDATEUI.equals(action)) {
                String log = b.getString("log");
                showLog(log);
            }
        }
    }

    StringBuffer sbLog = new StringBuffer();
    protected void showLog(String logLine) {
        DateFormat format = new java.text.SimpleDateFormat("MMddhhmmssSSS");
        String time = format.format(new Date());

        sbLog.append(time+":"+logLine);
        sbLog.append('\n');
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                View vText = findViewById(R.id.tv_log);

                if (vText != null && vText instanceof TextView) {
                    TextView tvLog = (TextView)vText;
                    tvLog.setText(sbLog.toString());
                }

                View vScrool = findViewById(R.id.sv_log);
                if (vScrool != null && vScrool instanceof ScrollView) {
                    ScrollView svLog = (ScrollView)vScrool;
                    svLog.fullScroll(View.FOCUS_DOWN);
                }
            }
        });
    }
    //如何判斷EMUI版本>=4.1
    private boolean isSwitchEnable(){
        int emuiApiLevel = 0;
        try {
            Class cls = Class.forName("android.os.SystemProperties");
            Method method = cls.getDeclaredMethod("get", new Class[]{String.class});
            emuiApiLevel = Integer.parseInt((String) method.invoke(cls, new Object[]{"ro.build.hw_emui_api_level"}));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return emuiApiLevel > 5.0;
    }
}

push.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF">

    <include
        android:id="@+id/layout_commom"
        layout="@layout/layout_head"/>

    <LinearLayout
        android:id="@+id/layout_first"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layout_commom"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_gettoken"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="獲取token"/>
        <Button
            android:id="@+id/btn_deletetoken"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="刪除token"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/layout_second"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layout_first"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_setnormal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="切換普通訊息開關"/>
        <Button
            android:id="@+id/btn_setnofify"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="切換通知訊息開關"/>

    </LinearLayout>

    <LinearLayout
        android:id="@+id/layout_third"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layout_second"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_agreement"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="協議"/>
        <Button
            android:id="@+id/btn_getpushstatus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="獲取push狀態"/>
    </LinearLayout>

    <ScrollView
        android:id="@+id/sv_log"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/layout_third">
        <TextView
            android:id="@+id/tv_log"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:textColor="#000000"
            android:paddingBottom="30dip"
            android:text="日誌顯示區:" />
    </ScrollView>

</RelativeLayout>

head.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:background="#FFFFFF"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_game"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="遊戲"/>
        <Button
            android:id="@+id/btn_iap"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="支付"/>
        <Button
            android:id="@+id/btn_id"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="帳號"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_sns"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="社交"/>
        <Button
            android:id="@+id/btn_push"
            android:includeFontPadding="false"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="push"/>
        <Button
            android:id="@+id/btn_opendevice"
            android:includeFontPadding="false"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_color"
            android:minWidth="60dp"
            android:text="開放裝置id"/>
    </LinearLayout>

</LinearLayout>

ok 大功告成。

由於我在獲取token的時候沒有返回值。

提單後告知 我小米手機 下載的最新華為移動服務 不支援。 也就沒測試了。 很難受。 

不過 以上方法 經過我多方驗證,把或許會犯錯的點已經 考慮了很多。

希望大家可以使用到。

推薦一個連線:

華為推送 超級多問題 都在這裡 。

微訪談: push 總結

官方Sample下載地址