版權聲明:本文為HaiyuKing原創文章,轉載請註明出處! 前言 這個Demo只是記錄華為推送的集成,不能運行。 另外,因為可能用到存儲許可權,所以還需要搭配運行時許可權申請功能。 使用步驟 一、項目組織結構圖 註意事項: 1、 導入類文件後需要change包名以及重新import R文件路徑 2、 ...
版權聲明:本文為HaiyuKing原創文章,轉載請註明出處!
前言
這個Demo只是記錄華為推送的集成,不能運行。
另外,因為可能用到存儲許可權,所以還需要搭配運行時許可權申請功能。
使用步驟
一、項目組織結構圖
註意事項:
1、 導入類文件後需要change包名以及重新import R文件路徑
2、 Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),如果項目中存在,則複製裡面的內容,不要整個覆蓋
二、導入步驟
2.1、接入準備
參考官網《接入準備》
註冊成為開發者——》創建應用——》獲取PUSH服務參數
最終是要能獲得appid值
2.2、下載SDK(HMS Agent套件 、HMS SDK兩個)
(1)下載HMS Agent套件
(2)下載HMS SDK
因為現在大部分是使用Android Studio開發環境,所以直接使用Gradle+maven集成方式。
2.3、先集成HMS SDK(集成HMS Agent套件在後面會講到)
(1)配置maven倉
在項目的build.gradle文件中添加以下代碼
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() //<!-- ======================華為推送SDK====================== --> maven {url 'http://developer.huawei.com/repo/'} } } task clean(type: Delete) { delete rootProject.buildDir }
(2)在子工程(module)的build.gradle文件中添加依賴
為了便於統一管理,我在demo中新創建了一個ThirdLib的module,集成華為推送SDK都放到ThirdLib這個module中。
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//華為推送SDK
api 'com.huawei.android.hms:push:2.6.1.301'
}
(3)同步修改的文件
(4)還需要在app的build.gradle文件中依賴thirdlib這個module
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.why.project.hwpushdemo"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//thirdlib
implementation project(':thirdlib')
}
2.4、集成HMS Agent套件
(1)解壓包
(2)執行GetHMSAgent_xx.bat生成copysrc的文件夾,裡面是根據您選擇需要集成HMS服務,抽取後的HMSAgent代碼(java 文件夾)和manifest文件(AndroidManifest.xml)
GetHMSAgent_cn.bat為中文腳本
GetHMSAgent_oversea.bat為英文腳本
此時,多了一個copysrc目錄
(3)拷貝copysrc/java裡面的代碼到您現有的工程。請保持HMSAgent代碼的包的路徑和結構不變
2.5、配置app這個module的AndroidManifest.xml
參考copysrc目錄下的AppManifestConfig.xml文件中的相關代碼和官網的資料!
註意,是app這個module,而不是thirdlib這個module!
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.why.project.hwpushdemo"> <!-- ======================華為推送SDK====================== --> <!--HMS-SDK引導升級HMS功能,訪問OTA伺服器需要網路許可權 | HMS-SDK upgrade HMS Feature, access to OTA server requires network privileges--> <uses-permission android:name="android.permission.INTERNET" /> <!--HMS-SDK引導升級HMS功能,保存下載的升級包需要SD卡寫許可權 | HMS-SDK upgrade HMS Feature, save downloaded upgrade pack requires SD card Write permission--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!--檢測網路狀態 | Detecting Network status--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!--檢測wifi狀態 | Detecting WiFi status--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!--獲取用戶手機的IMEI,用來唯一的標識設備。 | Gets the IMEI of the user's phone, used to uniquely identify the device.--> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!--如果是安卓8.0,應用編譯配置的targetSdkVersion>=26,請務必添加以下許可權 --> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <!-- 接收PUSH TOKEN的廣播以及PUSH消息需要定義該許可權 ${PACKAGE_NAME} 要替換上您應用的包名 --> <permission android:name="${applicationId}.permission.PROCESS_PUSH_MSG" android:protectionLevel="signatureOrSystem"/> <!--接收PUSH TOKEN的廣播以及PUSH消息需要定義該許可權 ${PACKAGE_NAME} 要替換上您應用的包名 --> <uses-permission android:name="${applicationId}.permission.PROCESS_PUSH_MSG" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <!-- ======================華為推送SDK====================== --> <!-- 接入HMSSDK 需要註冊的appid參數。value的值中“100222233444”用實際申請的appid替換,來源於開發者聯盟網站應用的權益詳情。 格式 android:value="appid=xxxxxx" Access HMSSDK need to register AppID parameters. Value "100223344" is replaced with the actual application APPID, derived from the Developer affiliate website application. Format android:value= "appid=xxxxxx"--> <meta-data android:name="com.huawei.hms.client.appid" android:value="appid=1000222233444"/> <!-- 接入HMSSDK 需要註冊的activity | Access HMSSDK activity to be registered 定義了HMS-SDK中一些跳轉所需要的透明頁面--> <activity android:name="com.huawei.hms.activity.BridgeActivity" android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale" android:excludeFromRecents="true" android:exported="false" android:hardwareAccelerated="true" android:theme="@android:style/Theme.Translucent" > <meta-data android:name="hwc-theme" android:value="androidhwext:style/Theme.Emui.Translucent" /> </activity> <!-- 接入HMSSDK 需要註冊的activity | Access HMSSDK activity to be registered 是應用自升級介面所需要使用的頁面--> <activity android:name="com.huawei.updatesdk.service.otaupdate.AppUpdateActivity" android:configChanges="orientation|screenSize" android:exported="false" android:theme="@style/upsdkDlDialog" > <meta-data android:name="hwc-theme" android:value="androidhwext:style/Theme.Emui.Translucent.NoTitleBar" /> </activity> <!-- 接入HMSSDK 需要註冊的activity | Access HMSSDK activity to be registered 是應用自升級介面所需要使用的頁面--> <activity android:name="com.huawei.updatesdk.support.pm.PackageInstallerActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:exported="false" android:theme="@style/upsdkDlDialog" > <meta-data android:name="hwc-theme" android:value="androidhwext:style/Theme.Emui.Translucent" /> </activity> <!-- 接入HMSSDK 需要註冊的provider,authorities 一定不能與其他應用一樣,所以這邊 com.why.project.hwpushdemo 要替換上您應用的包名 Access HMSSDK need to register provider,authorities must not be the same as other applications, so this side ${package_name} to replace the package name you applied 用於應用自升級--> <provider android:name="com.huawei.updatesdk.fileprovider.UpdateSdkFileProvider" android:authorities="com.why.project.hwpushdemo.updateSdk.fileProvider" android:exported="false" android:grantUriPermissions="true"> </provider> <!-- 接入HMSSDK 需要註冊的應用下載服務 | Access HMSSDK need to register app download service 用於應用自升級--> <service android:name="com.huawei.updatesdk.service.deamon.download.DownloadService" android:exported="false"/> <!-- 使用 HMSAgent 代碼接入HMSSDK 需要註冊的activity | Use hmsagent code to access HMSSDK activity that requires registration--> <!--解決華為移動服務升級問題的透明界面(必須聲明)--> <activity android:name="com.huawei.android.hms.agent.common.HMSAgentActivity" android:configChanges="orientation|locale|screenSize|layoutDirection|fontScale" android:excludeFromRecents="true" android:exported="false" android:hardwareAccelerated="true" android:theme="@android:style/Theme.Translucent" > <meta-data android:name="hwc-theme" android:value="androidhwext:style/Theme.Emui.Translucent" /> </activity> <!-- 接入HMSSDK 需要註冊的provider,authorities 一定不能與其他應用一樣,所以這邊 com.why.project.hwpushdemo 要替換上您應用的包名 Access HMSSDK need to register provider,authorities must not be the same as other applications, so this side ${package_name} to replace the package name you applied 用於HMS-SDK引導升級HMS,提供給系統安裝器讀取升級文件--> <provider android:name="com.huawei.hms.update.provider.UpdateProvider" android:authorities="com.why.project.hwpushdemo.hms.update.provider" android:exported="false" android:grantUriPermissions="true"/> <!-- 接入HMSSDK PUSH模塊需要註冊,第三方相關 :接收Push消息(註冊、Push消息、Push連接狀態)廣播, 此receiver類需要開發者自己創建並繼承com.huawei.hms.support.api.push.PushReceiver類, 參考示例代碼中的類:com.huawei.hmsagent.HuaweiPushRevicer Access to the HMSSDK push module requires registration: Receive push message (registration, push message, push connection state) broadcast. This receiver class requires the developer to create and inherit the com.huawei.hms.support.api.push.PushReceiver class. Reference to class in sample code: Com.huawei.hmsagent.HuaweiPushRevicer--> <!--用來接收PUSH消息的receiver--> <!-- 接入HMSSDK PUSH模塊需要註冊,第三方相關 :接收Push消息(註冊、Push消息、Push連接狀態)廣播, 此receiver類需要開發者自己創建並繼承com.huawei.hms.support.api.push.PushReceiver類, 參考示例代碼中的類:com.huawei.hmsagent.HuaweiPushRevicer Access to the HMSSDK push module requires registration: Receive push message (registration, push message, push connection state) broadcast. This receiver class requires the developer to create and inherit the com.huawei.hms.support.api.push.PushReceiver class. Reference to class in sample code: Com.huawei.hmsagent.HuaweiPushRevicer--> <receiver android:name="com.why.project.hwpushdemo.huaweipush.HuaweiPushRevicer" > <intent-filter> <!-- 必須,用於接收token | Must, for receiving token --> <action android:name="com.huawei.android.push.intent.REGISTRATION" /> <!-- 必須,用於接收消息 | Must, used to receive messages--> <action android:name="com.huawei.android.push.intent.RECEIVE" /> <!-- 可選,用於點擊通知欄或通知欄上的按鈕後觸發onEvent回調 | Optional, click the button on the notification bar or the notification bar to trigger the onevent callback --> <action android:name="com.huawei.android.push.intent.CLICK" /> <!-- 可選,查看push通道是否連接,不查看則不需要 | Optional, query whether the push channel is connected or not --> <action android:name="com.huawei.intent.action.PUSH_STATE" /> </intent-filter> </receiver> <!-- 接入HMSSDK PUSH模塊需要註冊 :接收通道發來的通知欄消息 | The access HMSSDK push module needs to be registered: the notification bar message sent from the receiving channel --> <!--接收通道發來的通知欄消息--> <receiver android:name="com.huawei.hms.support.api.push.PushEventReceiver" > <intent-filter> <action android:name="com.huawei.intent.action.PUSH" /> </intent-filter> </receiver> <!-- 華為推送自定義動作打開的界面【需要透明】,需要註意scheme必須設置唯一的,和手機上其他的APP使用的scheme不一樣 --> <!--hwdemoscheme://{包名}/notify_detail?title={標題}&content={內容}--> <activity android:name="com.why.project.hwpushdemo.huaweipush.HWpushActivity" android:theme="@android:style/Theme.Translucent"> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:host="${applicationId}" android:path="/notify_detail" android:scheme="hwdemoscheme"/> </intent-filter> </activity> </application> </manifest>
1、appid需要換成自己的;
2、將黃色標記的代碼中的包名(com.why.project.hwpushdemo)全部替換成自己的包名(如果是從copysrc的AppManifestConfig.xml文件複製的代碼,直接是自己的包名);
3、HuaweiPushRevicer【華為推送的回調,比如獲取token】的完整路徑需要更換成真實的;
4、HWpushActivity【點擊通知後打開的界面】的完整路徑需要更換成真實的;
5、HWpushActivity下的host、path、scheme要換成自己項目的,另外這三個欄位的值在推送的時候用的到;
2.6、將HuaweiPushRevicer、HWpushActivity添加到項目中
其中,HuaweiPushRevicer不用管,HWpushActivity需要根據實際情況修改下,activity_hwpush.xml文件不用管,就是個空佈局。
package com.why.project.hwpushdemo.huaweipush; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import com.why.project.hwpushdemo.R; import org.json.JSONObject; /** * Created by HaiyuKing * Used 華為推送自定義動作打開的界面【華為推送SDK】 * https://www.jianshu.com/p/3b0df1c976a5 * https://blog.csdn.net/gaoshang0304/article/details/80463246 * https://blog.csdn.net/nsacer/article/details/80346965 * https://blog.csdn.net/u013904672/article/details/71079278 */ public class HWpushActivity extends Activity { private static final String TAG = HWpushActivity.class.getSimpleName(); private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hwpush); mContext = this; //獲取自定義動作的值 Intent intent = getIntent(); String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME); Log.e(TAG,"action是:" + intentUri); //intent://com.why.project.hwpushdemo/notify_detail?title=測試標題&content=測試內容&exTraTitle=界面標題&url=http://www.baidu.com#Intent;scheme=hwdemoscheme;launchFlags=0x13000000;component=com.why.project.hwpushdemo/.huaweipush.HWpushActivity;end //關閉當前界面,跳轉到指定的界面 try { String title = getIntent().getData().getQueryParameter("title"); String content = getIntent().getData().getQueryParameter("content"); String exTraTitle = getIntent().getData().getQueryParameter("exTraTitle"); String url = getIntent().getData().getQueryParameter("url"); JSONObject extraJson = new JSONObject(); extraJson.put("exTraTitle",exTraTitle); extraJson.put("url",url); Bundle bundle = new Bundle(); bundle.putString(JPushInterface.EXTRA_NOTIFICATION_TITLE,title);//通知的標題 bundle.putString(JPushInterface.EXTRA_ALERT,content);//通知內容 bundle.putString(JPushInterface.EXTRA_EXTRA,extraJson.toString());//通知附加欄位 bundle.putInt(JPushInterface.EXTRA_NOTIFICATION_ID,0);//通知id值【沒什麼用】 Intent i = new Intent(mContext, JpushActivity.class); i.putExtras(bundle); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//必須使用這個,這個保證了多個通知,點擊返回返回到的是上一個通知界面 mContext.startActivity(i); finish(); } catch (Exception e){ e.printStackTrace(); } } }
這裡稍微講解下,這個activity的主要作用是下麵兩點:
1、獲取自定義動作的值;
2、關閉當前界面,跳轉到指定的界面(傳值過去);
上面代碼中跳轉界面那裡(橙色標記的代碼),是需要根據實際情況修改的。
2.7、將JpushActivity添加到項目中(僅供參考)
package com.why.project.hwpushdemo; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.KeyEvent; import android.view.View; import android.widget.TextView; import org.json.JSONException; import org.json.JSONObject; /** * Used 極光推送點開通知後打開的界面 * 和WebViewPreviewActivity共用一個佈局文件 * 需要先檢查是否已經登錄,如果沒有登錄,直接登錄即可,不需要返回到登錄界面了 * 極光推送SDK */ public class JpushActivity extends AppCompatActivity { private static final String TAG = JpushActivity.class.getSimpleName(); /**從登錄界面打開的標記(傳遞參數用)*/ public static final String EXTRA_ONLOGIN = "onlogin"; /*Jpush傳遞過來的參數*/ private Bundle jPushBundle; /**通知標題*/ private String jPushTitle; /**通知內容*/ private String jPushContent; /**通知附加欄位*/ private String jPushExtraJson; /**通知id值*/ private int jPushId; //展現在導航欄上的標題 private String bundle_title; //網頁url地址 private String bundle_url; /**標記是否從登錄界面打開的狀態值*/ private boolean bundle_onlogin = false; private Context mContext; private Toolbar mToolbar; private MyWebView myWebView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_webviewpreview); mContext = this; //初始化控制項 initViews(); //初始化數據 initData(); initToolBar();//初始化toolbar } @Override public void onDestroy() { //銷毀webview控制項 myWebView.removeAllViews(); myWebView.destroy(); super.onDestroy(); } /** * 初始化view */ private void initViews() { myWebView = (MyWebView)findViewById(R.id.id_webView); myWebView.setCanBackPreviousPage(true,JpushActivity.this);//可以返回上一頁 } /** * 初始化數據【接收點擊通知欄傳過來的數據:通知、自定義消息兩種(這裡只需要處理通知的即可)】 */ private void initData() { Intent intent = getIntent(); if (null != intent) { jPushBundle = getIntent().getExtras(); jPushTitle = jPushBundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);//保存伺服器推送下來的通知的標題 jPushContent = jPushBundle.getString(JPushInterface.EXTRA_ALERT);//保存伺服器推送下來的通知內容 jPushExtraJson = jPushBundle.getString(JPushInterface.EXTRA_EXTRA);//保存伺服器推送下來的附加欄位。這是個 JSON 字元串 jPushId = jPushBundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);//SDK 1.3.5 以上版本支持,通知欄的Notification ID,可以用於清除Notification bundle_onlogin = jPushBundle.getBoolean(EXTRA_ONLOGIN); } if(!jPushExtraJson.equals("")){ try { JSONObject extraJsonObj = new JSONObject(jPushExtraJson); if(extraJsonObj.has("from")){ extraJsonObj = new JSONObject(extraJsonObj.getString("from")); } if(!extraJsonObj.getString("exTraTitle").equals("")){ //獲取標題 bundle_title = extraJsonObj.getString("exTraTitle"); } if(!extraJsonObj.getString("url").equals("")){ //獲取網頁地址 bundle_url = extraJsonObj.getString("url"); } } catch (Resources.NotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(! bundle_onlogin){//如果是從登錄界面打開的話,那麼不用驗證了 initCheckLoginState();//驗證是否需要重新登錄 }else{ loadWebUrl();//打開網頁 } } private void initToolBar() { mToolbar = findViewById(R.id.toolbar_base); mToolbar.setTitle("");//這樣設置的話,自帶的標題就不會顯示 //設置自定義的標題(居中) TextView toolBarTitle = mToolbar.findViewById(R.id.toolbarTitle); toolBarTitle.setText(bundle_title); setSupportActionBar(mToolbar);//由於toolbar只是一個普通控制項,我們將ToolBar設置為ActionBar //設置導航圖標要在setSupportActionBar方法之後 mToolbar.setNavigationIcon(R.drawable.nav_back);//設置為空的話,就會不顯示左側的圖標 //對NavigationIcon添加點擊 mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //返回到首頁界面(重新登錄的情況下)或者直接關閉自己(不需要重新登錄的情況下) backHomeOrFinish(); } }); } /** * 點擊返回鍵 * event.getRepeatCount() == 0:點後退鍵的時候,為了防止點得過快,觸發兩次後退事件,故做此設置。 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { //返回到首頁界面(如果是從登錄界面打開的)或者關閉自己(從通知打開的) backHomeOrFinish(); } return super.onKeyDown(keyCode, event); } //返回功能 private void backHomeOrFinish() { if (bundle_onlogin) { ActivityJump.NormalJumpAndFinish(JpushActivity.this, HomeActivity.class); } else { ActivityJump.Back(this); } } /** * 網路請求檢查登錄狀態,主要判斷是否線上 */ private void initCheckLoginState() { if(result.indexOf("alert(") != -1){ //登陸身份失效,請重新登陸 ActivityJump.BundleJumpAndFinish(JpushActivity.this, LoginActivity.class,jPushBundle); } else{ loadWebUrl();//載入網頁 } } /** * 載入URL地址 */ private void loadWebUrl() { syncCookie(JpushActivity.this, ServerApi.SERVER_URL); if (!bundle_url.equals("")) { myWebView.loadWebUrl(ServerApi.SERVER_URL + bundle_url); } else { myWebView.loadUrl("about:blank");//載入一個空白頁 } } /** * Sync Cookie */ public static void syncCookie(Context context, String url){ //參考本博客的《okhttputils【 Android 一個改善的okHttp封裝庫】使用(二)》 } }
3、初始化Agent
在application的onCreate方法中初始化HMSAgent。如果沒有自己的application類,請創建併在manifest文件中配置application節點的name屬性。
package com.why.project.hwpushdemo; import android.app.Application; import com.huawei.android.hms.agent.HMSAgent; /** * Created by HaiyuKing * Used */ public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); //華為推送SDK initHuaWeiPush(); } //華為推送SDK private void initHuaWeiPush(){ HMSAgent.init(this); } @Override public void onTerminate() { super.onTerminate(); //華為推送SDK HMSAgent.destroy(); } }
4、調用connect介面
建議在應用啟動時調用Connect。在哪個Activity中調用,哪個Activity的alertDialog不彈出,返回軟鍵點擊後無響應。
package com.why.project.hwpushdemo; import android.content.Context; import android.content.Intent; import