版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!android
這個Demo只是記錄極光推送的集成,不能運行。web
注意事項:json
一、 導入類文件後須要change包名以及從新import R文件路徑api
二、 Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋服務器
參考官網《3 分鐘快速使用 JPush Android Demo》網絡
建立極光推送開發者賬號——》建立應用——》獲取APPkeyapp
若是使用自動集成的話,不須要下載SDK,不過我我的傾向於手動集成,因此須要下載SDK。ide
下載地址:https://docs.jiguang.cn/jpush/resources/佈局
下載後的壓縮包解壓後的目錄:gradle
說明:
爲了便於管理,我在Demo中新建了一個ThirdLib的module,用於集成SDK。
//引用thirdlib
implementation project(':thirdlib')
由於是在thirdlib這個module中集成jar包,因此還須要在thirdlib這個module的build.gradle文件中引用libs目錄下的jar包。
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 files('libs/jcore-android-1.2.6.jar') api files('libs/jpush-android-3.1.8.jar')
}
注意下面標記橙色代碼:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.why.project.jpushdemo"> <!-- ======================極光推送SDK====================== --> <!-- Required --> <permission android:name="${applicationId}.permission.JPUSH_MESSAGE" android:protectionLevel="signature" /> <!-- Required 一些系統要求的權限,如訪問網絡等--> <uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" /> <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!--(必須須要,不然設置別名失敗)--> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!--(必須須要,不然設置別名失敗)--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Optional for location --> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用於開啓 debug 版本的應用在6.0 系統上 層疊窗口權限 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.GET_TASKS" /> <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========================== --> <!-- 狀態通知欄須要打開的Activity --> <activity android:name="com.why.project.jpushdemo.jpush.JpushActivity" android:exported="false"> <intent-filter> <action android:name="jpush.testAction" /> <category android:name="jpush.testCategory" /> </intent-filter> </activity> <!-- Rich push 核心功能 since 2.0.6--> <activity android:name="cn.jpush.android.ui.PopWinActivity" android:theme="@style/MyDialogStyle" android:exported="false"> </activity> <!-- Required SDK核心功能--> <activity android:name="cn.jpush.android.ui.PushActivity" android:configChanges="orientation|keyboardHidden" android:theme="@android:style/Theme.NoTitleBar" android:exported="false"> <intent-filter> <action android:name="cn.jpush.android.ui.PushActivity" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="${applicationId}" /> </intent-filter> </activity> <!-- Required SDK 核心功能--> <!-- 可配置android:process參數將PushService放在其餘進程中 --> <service android:name="cn.jpush.android.service.PushService" android:process=":pushcore" android:exported="false"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTER" /> <action android:name="cn.jpush.android.intent.REPORT" /> <action android:name="cn.jpush.android.intent.PushService" /> <action android:name="cn.jpush.android.intent.PUSH_TIME" /> </intent-filter> </service> <!-- since 3.0.9 Required SDK 核心功能--> <provider android:authorities="${applicationId}.DataProvider" android:name="cn.jpush.android.service.DataProvider" android:process=":pushcore" android:exported="false" /> <!-- since 1.8.0 option 可選項。用於同一設備中不一樣應用的JPush服務相互拉起的功能。 --> <!-- 若不啓用該功能可刪除該組件,將不拉起其餘應用也不能被其餘應用拉起 --> <service android:name="cn.jpush.android.service.DaemonService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="cn.jpush.android.intent.DaemonService" /> <category android:name="${applicationId}" /> </intent-filter> </service> <!-- since 3.1.0 Required SDK 核心功能--> <provider android:authorities="${applicationId}.DownloadProvider" android:name="cn.jpush.android.service.DownloadProvider" android:exported="true" /> <!-- Required SDK核心功能--> <receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true" android:exported="false"> <intent-filter android:priority="1000"> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 顯示通知欄 --> <category android:name="${applicationId}" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> <!-- Optional --> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver> <!-- Required SDK核心功能--> <receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/> <!-- User defined. For test only 用戶自定義的廣播接收器--> <receiver android:name="com.why.project.jpushdemo.jpush.JpushReceiver" android:exported="false" android:enabled="true"> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required 用戶註冊SDK的intent--> <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required 用戶接收SDK消息的intent--> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required 用戶接收SDK通知欄信息的intent--> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required 用戶打開自定義通知欄的intent--> <action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收網絡變化 鏈接/斷開 since 1.6.3 --> <category android:name="${applicationId}" /> </intent-filter> </receiver> <!-- User defined. For test only 用戶自定義接收消息器,3.0.7開始支持,目前新tag/alias接口設置結果會在該廣播接收器對應的方法中回調--> <receiver android:name="com.why.project.jpushdemo.jpush.MyJPushMessageReceiver"> <intent-filter> <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /> <category android:name="${applicationId}"></category> </intent-filter> </receiver> <!-- Required . Enable it you can get statistics data with channel --> <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/> <meta-data android:name="JPUSH_APPKEY" android:value="9fed5bcb7b9b87413678c407" /> <!-- </>值來自開發者平臺取得的AppKey--> </application> </manifest>
其中,關鍵的是JpushActivity和JpushReceiver這兩個文件。
JpushReceiver:主要用於點開通知欄,判斷跳轉打開的界面
JpushActivity:主要用於展示點擊通知打開的界面;
package com.why.project.jpushdemo.jpush; 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 com.why.project.jpushdemo.R; import org.json.JSONException; import org.json.JSONObject; import cn.jpush.android.api.JPushInterface; /** * 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封裝庫】使用(二)》 } }
在MyApplication中執行
package com.why.project.jpushdemo; import android.app.Application; import cn.jpush.android.api.JPushInterface; /** * Created by HaiyuKing * Used */ public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); initJpush();//極光推送SDK初始化 } //極光推送SDK private void initJpush() { JPushInterface.setDebugMode(true);// 設置開啓日誌,發佈時請關閉日誌 JPushInterface.init(this);// 初始化 JPush } }
package com.why.project.jpushdemo; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import com.why.project.jpushdemo.jpush.ExampleUtil; import com.why.project.jpushdemo.jpush.TagAliasOperatorHelper; import cn.jpush.android.api.JPushInterface; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; /*=======================================極光推送SDK相關=============================================*/ //請求服務器刪除alias,而後再從新註冊alias,這樣實現一個別名只能綁定一臺設備 updateJpushDeviceId(); } /*=======================================極光推送SDK相關=============================================*/ /** * 更新設備id接口 */ private void updateJpushDeviceId() { String regId = JPushInterface.getRegistrationID(mContext);//可能不會那麼快就能得到resId值,因此若是極光推送沒有初始化好,那麼這裏獲取到的是null requestDeviceId(regId);//判斷是請求接口仍是彈出對話框 } //請求接口存儲設備id或者token的方法 private void requestDeviceId(String regId) { //首要條件是設備id值或者token值不爲空,不然下面的判斷沒有意義了 //若是沒有設置過別名,或者則須要設置別名 //若是服務器上的deviceID值是空值,代表當前用戶尚未綁定任何設備,則直接請求接口,不須要彈出對話框; //若是服務器上的deviceID值不爲空,而且客戶端獲取的設備id值和服務器上的deviceID值相同,則不須要彈出對話框,直接請求接口(這個是卸載從新安裝的狀況) //若是服務器上的deviceid值不爲空,而且客戶端獲取的設備id值和服務器上的deviceID值不一樣,則須要彈出對話框(這個是換設備的狀況) if (!TextUtils.isEmpty(regId)) { //若是已經設置過別名(存儲過了設備id值)了,可是當前的別名(設備id值)和服務器上的不一致,則須要從新設置別名(存儲設備id值)(這個是其餘設備上登陸的狀況) } //設置極光推送別名 setAlias(PreferencesUtils.getString(mContext,Globals.USERNAME_KEY)); } // 這是來自 JPush Example 的設置別名的 Activity 裏的代碼。通常 App 的設置的調用入口,在任何方便的地方調用均可以。 private void setAlias(String alias) { if (TextUtils.isEmpty(alias)) { ToastUtil.showShortToast(getResources().getString(R.string.error_alias_empty));//alias別名不能爲空 return; } if (!ExampleUtil.isValidTagAndAlias(alias)) { ToastUtil.showShortToast(getResources().getString(R.string.error_tag_gs_empty));//格式不對 return; } // 調用 JPush 接口來設置別名。 TagAliasOperatorHelper.TagAliasBean tagAliasBean = new TagAliasOperatorHelper.TagAliasBean(); tagAliasBean.action = TagAliasOperatorHelper.ACTION_SET; tagAliasBean.alias = alias; tagAliasBean.isAliasAction = true; TagAliasOperatorHelper.getInstance().handleAction(MyApplication.getAppContext(), TagAliasOperatorHelper.sequence++, tagAliasBean); //已經設置了別名 String aliasKey = Globals.UPDATEJPUSHRESID_KEY; PreferencesUtils.putBoolean(mContext,aliasKey,true); } }
#====極光推送SDK====
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
暫時空缺
連接:https://pan.baidu.com/s/1eHSnRrw07LC9mq1I7IP2gw 提取碼:wn99