├── .gitignore ├── app ├── .gitignore ├── app-release.apk ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── bearever │ │ └── pushdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── bearever │ │ │ └── pushdemo │ │ │ ├── MainActivity.java │ │ │ └── MyApplication.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── bearever │ └── pushdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img ├── PushMind.png ├── folder.png ├── 微信截图_20180531110846.png ├── 微信截图_20180531111009.png ├── 微信截图_20180531111115.png └── 微信截图_20181009150639.png ├── push ├── .gitignore ├── build.gradle ├── libs │ ├── HMS_SDK_2.6.0.301.jar │ ├── MiPush_SDK_Client_3_6_2.jar │ ├── arm64-v8a │ │ └── libjcore121.so │ ├── armeabi-v7a │ │ └── libjcore121.so │ ├── armeabi │ │ └── libjcore121.so │ ├── com.coloros.mcssdk.jar │ ├── jcore-android-1.2.1.jar │ ├── jpush-android-3.1.3.jar │ ├── mips │ │ └── libjcore121.so │ ├── mips64 │ │ └── libjcore121.so │ ├── push-internal-3.8.1.aar │ ├── pushsdk_v2.3.4.jar │ ├── x86 │ │ └── libjcore121.so │ └── x86_64 │ │ └── libjcore121.so ├── proguard-rules.pro ├── readme.md └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ ├── bearever │ │ └── push │ │ │ ├── OnTokenGetListener.java │ │ │ ├── PushTargetManager.java │ │ │ ├── model │ │ │ ├── PushTarget.java │ │ │ ├── PushTargetEnum.java │ │ │ └── ReceiverInfo.java │ │ │ ├── receiver │ │ │ ├── BasePushBroadcastReceiver.java │ │ │ └── PushReceiverHandleManager.java │ │ │ ├── target │ │ │ ├── BasePushTargetInit.java │ │ │ ├── huawei │ │ │ │ ├── HuaweiInit.java │ │ │ │ ├── HuaweiLoadActivity.java │ │ │ │ └── HuaweiPushBroadcastReceiver.java │ │ │ ├── jiguang │ │ │ │ ├── IJPushEventReceiver.java │ │ │ │ ├── JPushBroadcastReceiver.java │ │ │ │ └── JPushInit.java │ │ │ ├── meizu │ │ │ │ ├── MeizuInit.java │ │ │ │ └── MeizuMessageReceiver.java │ │ │ ├── oppo │ │ │ │ ├── OppoInit.java │ │ │ │ ├── OppoLoadActivity.java │ │ │ │ └── OppoMessageService.java │ │ │ ├── vivo │ │ │ │ ├── VivoBroadcastReceiver.java │ │ │ │ └── VivoInit.java │ │ │ └── xiaomi │ │ │ │ ├── XiaomiBroadcastReceiver.java │ │ │ │ └── XiaomiInit.java │ │ │ └── util │ │ │ └── ApplicationUtil.java │ │ └── huawei │ │ └── android │ │ └── hms │ │ └── agent │ │ ├── HMSAgent.java │ │ ├── common │ │ ├── ActivityMgr.java │ │ ├── ApiClientMgr.java │ │ ├── BaseAgentActivity.java │ │ ├── BaseApiAgent.java │ │ ├── CallbackCodeRunnable.java │ │ ├── CallbackResultRunnable.java │ │ ├── EmptyConnectCallback.java │ │ ├── HMSAgentActivity.java │ │ ├── HMSAgentLog.java │ │ ├── IActivityDestroyedCallback.java │ │ ├── IActivityPauseCallback.java │ │ ├── IActivityResumeCallback.java │ │ ├── ICallbackCode.java │ │ ├── ICallbackResult.java │ │ ├── IClientConnectCallback.java │ │ ├── INoProguard.java │ │ ├── IOUtils.java │ │ ├── StrUtils.java │ │ ├── ThreadUtil.java │ │ └── handler │ │ │ └── ConnectHandler.java │ │ └── push │ │ ├── DeleteTokenApi.java │ │ ├── EnableReceiveNormalMsgApi.java │ │ ├── EnableReceiveNotifyMsgApi.java │ │ ├── GetPushStateApi.java │ │ ├── GetTokenApi.java │ │ ├── QueryAgreementApi.java │ │ └── handler │ │ ├── DeleteTokenHandler.java │ │ ├── EnableReceiveNormalMsgHandler.java │ │ ├── EnableReceiveNotifyMsgHandler.java │ │ ├── GetPushStateHandler.java │ │ ├── GetTokenHandler.java │ │ └── QueryAgreementHandler.java │ └── res │ ├── values-zh-rCN │ └── hms_values-zh-rCN.xml │ └── values │ ├── colors.xml │ ├── hms_values.xml │ ├── strings.xml │ └── styles.xml ├── pushdemo.jks ├── readme.md └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/app-release.apk -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '26.0.2' 6 | defaultConfig { 7 | applicationId "com.bearever.pushdemo" 8 | minSdkVersion 15 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | signingConfigs { 17 | // debug { 18 | // keyAlias 'pushdemo' 19 | // keyPassword '123456' 20 | // storeFile file('E:/AndroidStudioProjects/PushDemo/pushdemo.jks') 21 | // storePassword '123456' 22 | // } 23 | } 24 | 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | 31 | debug { 32 | // signingConfig signingConfigs.debug 33 | 34 | } 35 | } 36 | 37 | repositories { 38 | flatDir { 39 | dirs project(':push').file('libs') 40 | } 41 | } 42 | 43 | } 44 | 45 | dependencies { 46 | 47 | compile fileTree(include: ['*.jar'], dir: 'libs') 48 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 49 | exclude group: 'com.android.support', module: 'support-annotations' 50 | }) 51 | compile 'com.android.support:appcompat-v7:26.+' 52 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 53 | testCompile 'junit:junit:4.12' 54 | compile project(':push') 55 | } 56 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/bearever/pushdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.bearever.pushdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.bearever.pushdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/bearever/pushdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.bearever.pushdemo; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import com.bearever.push.PushTargetManager; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | PushTargetManager.getInstance().init(getApplication()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/bearever/pushdemo/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.bearever.pushdemo; 2 | 3 | import android.app.Application; 4 | 5 | import com.bearever.push.PushTargetManager; 6 | 7 | /** 8 | * Created by luoming on 2018/5/28. 9 | */ 10 | 11 | public class MyApplication extends Application { 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | 16 | PushTargetManager.getInstance().init(this); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | PushDemo 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/bearever/pushdemo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.bearever.pushdemo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.3.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri May 25 16:35:40 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /img/PushMind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/PushMind.png -------------------------------------------------------------------------------- /img/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/folder.png -------------------------------------------------------------------------------- /img/微信截图_20180531110846.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/微信截图_20180531110846.png -------------------------------------------------------------------------------- /img/微信截图_20180531111009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/微信截图_20180531111009.png -------------------------------------------------------------------------------- /img/微信截图_20180531111115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/微信截图_20180531111115.png -------------------------------------------------------------------------------- /img/微信截图_20181009150639.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/img/微信截图_20181009150639.png -------------------------------------------------------------------------------- /push/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /push/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '26.0.2' 6 | 7 | defaultConfig { 8 | manifestPlaceholders = [ 9 | "jPushAppkey" : "ea6c961e572ad972df4ef456",//极光推送的AppKey 10 | "huaweiPushAppId" : "100698925",//华为推送的AppId 11 | "xiaomiPushAppkey": "55617974 54571",//"57417800 14675",//小米推送的AppKey****请务必在数值中间添加一个空格,否则会发生数值变化**** 12 | "xiaomiPushAppId" : "28823037 61517974571",//"28823037 61517800675",//小米推送的AppID****请务必在数值中间添加一个空格,否则会发生数值变化**** 13 | "oppoAppKey" : "9d24177594c741be86465ec9fe490a44",//OPPO推送的appKey 14 | "oppoAppSecret" : "c60bec1f803e49e88037562ec2109286",//OPPO推送的appSecret 15 | "meizuAppId" : "1200 55",//魅族推送AppId ****请务必在数值中间添加一个空格,否则会发生数值变化**** 16 | "meizuAppKey" : "3aca7449444347c4a1d2a70826ae1e9b",//魅族推送AppKey 17 | "vivoAppId" : "11937",//vivo推送AppId 18 | "vivoAppKey" : "acfdb480-e178-4098-80ae-76284df7d588",//vivo推送AppKey 19 | "marketChannel" : "develops"//渠道 20 | ] 21 | 22 | minSdkVersion 15 23 | targetSdkVersion 26 24 | versionCode 1 25 | versionName "1.0" 26 | 27 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 28 | } 29 | buildTypes { 30 | release { 31 | minifyEnabled false 32 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 33 | } 34 | } 35 | 36 | sourceSets { 37 | main { 38 | jniLibs.srcDirs = ['libs'] 39 | } 40 | } 41 | repositories { 42 | flatDir { 43 | dirs 'libs' 44 | } 45 | } 46 | } 47 | 48 | dependencies { 49 | compile fileTree(include: ['*.jar'], dir: 'libs') 50 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 51 | exclude group: 'com.android.support', module: 'support-annotations' 52 | }) 53 | compile 'com.android.support:appcompat-v7:26.+' 54 | testCompile 'junit:junit:4.12' 55 | compile files('libs/jcore-android-1.2.1.jar') 56 | compile files('libs/jpush-android-3.1.3.jar') 57 | compile files('libs/MiPush_SDK_Client_3_6_2.jar') 58 | compile files('libs/HMS_SDK_2.6.0.301.jar') 59 | compile 'com.google.code.gson:gson:2.2.4' 60 | compile(name: 'push-internal-3.8.1', ext: 'aar') 61 | 62 | } 63 | -------------------------------------------------------------------------------- /push/libs/HMS_SDK_2.6.0.301.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/HMS_SDK_2.6.0.301.jar -------------------------------------------------------------------------------- /push/libs/MiPush_SDK_Client_3_6_2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/MiPush_SDK_Client_3_6_2.jar -------------------------------------------------------------------------------- /push/libs/arm64-v8a/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/arm64-v8a/libjcore121.so -------------------------------------------------------------------------------- /push/libs/armeabi-v7a/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/armeabi-v7a/libjcore121.so -------------------------------------------------------------------------------- /push/libs/armeabi/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/armeabi/libjcore121.so -------------------------------------------------------------------------------- /push/libs/com.coloros.mcssdk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/com.coloros.mcssdk.jar -------------------------------------------------------------------------------- /push/libs/jcore-android-1.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/jcore-android-1.2.1.jar -------------------------------------------------------------------------------- /push/libs/jpush-android-3.1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/jpush-android-3.1.3.jar -------------------------------------------------------------------------------- /push/libs/mips/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/mips/libjcore121.so -------------------------------------------------------------------------------- /push/libs/mips64/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/mips64/libjcore121.so -------------------------------------------------------------------------------- /push/libs/push-internal-3.8.1.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/push-internal-3.8.1.aar -------------------------------------------------------------------------------- /push/libs/pushsdk_v2.3.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/pushsdk_v2.3.4.jar -------------------------------------------------------------------------------- /push/libs/x86/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/x86/libjcore121.so -------------------------------------------------------------------------------- /push/libs/x86_64/libjcore121.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/push/libs/x86_64/libjcore121.so -------------------------------------------------------------------------------- /push/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | 27 | #极光推送start 28 | -dontoptimize 29 | -dontpreverify 30 | 31 | -dontwarn cn.jpush.** 32 | -keep class cn.jpush.** { *; } 33 | -keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; } 34 | 35 | -dontwarn cn.jiguang.** 36 | -keep class cn.jiguang.** { *; } 37 | #极光推送end 38 | 39 | #小米推送start 40 | -keep class com.bearever.push.target.xiaomi.XiaomiBroadcastReceiver {*;} 41 | -dontwarn com.xiaomi.push.** 42 | #小米推送end 43 | 44 | #华为推送start 45 | -ignorewarning 46 | -keepattributes *Annotation* 47 | -keepattributes Exceptions 48 | -keepattributes InnerClasses 49 | -keepattributes Signature 50 | -keepattributes SourceFile,LineNumberTable 51 | -keep class com.hianalytics.android.**{*;} 52 | -keep class com.huawei.updatesdk.**{*;} 53 | -keep class com.huawei.hms.**{*;} 54 | 55 | -keep class com.huawei.gamebox.plugin.gameservice.**{*;} 56 | 57 | -keep public class com.huawei.android.hms.agent.** extends android.app.Activity { public *; protected *; } 58 | -keep interface com.huawei.android.hms.agent.common.INoProguard {*;} 59 | -keep class * extends com.huawei.android.hms.agent.common.INoProguard {*;} 60 | #华为推送end 61 | 62 | #OPPO推送 start 63 | -keep public class * extends android.app.Service 64 | #OPPO推送 end 65 | 66 | #VIVO推送 start 67 | -dontwarn com.vivo.push.**-keep class com.vivo.push.**{*; } 68 | -keep class com.vivo.vms.**{*; } 69 | -keep class xxx.xxx.xxx.PushMessageReceiverImpl{*;} 70 | #VIVO推送 end 71 | -------------------------------------------------------------------------------- /push/readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Push 3 | 4 | 一个推送的模块,集成了华为、小米、魅族、OPPO和极光推送,根据设备厂商判断使用具体哪个SDK如:小米手机使用小米推送,华为手机使用华为推送,其他的设备使用极光推送。 5 | 6 | ## 更新时间 7 | 8 | 2019/04/18 9 | 10 | 添加统一接收消息的`BasePushBroadcastReceiver`和vivo推送平台 11 | 12 | ## 使用 13 | 14 | ### 1.配置AppKey 15 | 16 | 在您的app 的gradle配置文件里面添加如下代码: 17 | 18 | ```groovy 19 | defaultConfig { 20 | manifestPlaceholders = [ 21 | "jPushAppkey" : "ea6c961e572ad972df4ef456",//极光推送的AppKey 22 | "huaweiPushAppId" : "100698925",//华为推送的AppId 23 | "xiaomiPushAppkey": "55617974 54571",//"57417800 14675",//小米推送的AppKey****请务必在数值中间添加一个空格,否则会发生数值变化**** 24 | "xiaomiPushAppId" : "28823037 61517974571",//"28823037 61517800675",//小米推送的AppID****请务必在数值中间添加一个空格,否则会发生数值变化**** 25 | "oppoAppKey" : "9d24177594c741be86465ec9fe490a44",//OPPO推送的appKey 26 | "oppoAppSecret" : "c60bec1f803e49e88037562ec2109286",//OPPO推送的appSecret 27 | "meizuAppId" : "1200 55",//魅族推送AppId ****请务必在数值中间添加一个空格,否则会发生数值变化**** 28 | "meizuAppKey" : "3aca7449444347c4a1d2a70826ae1e9b",//魅族推送AppKey 29 | "vivoAppId" : "11937",//vivo推送AppId 30 | "vivoAppKey" : "acfdb480-e178-4098-80ae-76284df7d588",//vivo推送AppKey 31 | "marketChannel" : "develops"//渠道 32 | ] 33 | } 34 | ``` 35 | 36 | 在push模块下面的`buid.gradle`文件里面替换对应的AppKey,**需要注意的地方**: 37 | 38 | > 小米的AppKey和魅族的AppId是使用的数字的格式,不能直接复制粘粘到文件里面,需要在中间增加一个空格,例如:AppKey为`201584151343514321321`需要替换为`20158415134 3514321321` 39 | 40 | ### 2.配置华为推送 41 | 42 | 华为推送的SDK是通过工具生成的,所以需要手动配置生成代码,先[下载华为HMS Agent套件](https://obs.cn-north-2.myhwclouds.com/hms-ds-wf/sdk/HMSAgent_2.6.1.302.zip),解压出来之后根据自己的电脑系统需要相应的脚本文件,例如:Window点击双击`GetHMSAgent_cn.bat`在弹出的窗口里面根据提示操作就好了,最后生存的代码会保存在`copysrc`文件夹里面。将生成的代码复制到Push的java目录下面,res资源文件根据需要添加到资源目录下。 43 | 44 | ### 3.初始化 45 | 46 | 在Application的onCreate里面调用`PushTargetManager`的`init`方法。 47 | 48 | ### 4.处理推送消息 49 | 50 | 推送的信息分为`Message`和`Notification`,Notification会主动在通知栏显示通知,而Message不会。 51 | 52 | 要处理接收到的信息,只需要实现`BasePushBroadcastReceiver`或者`PushTargetManager.getInstance().addPushReceiverListener(String, OnPushReceiverListener)`方法即可。 53 | 54 | #### 4.1自定义BasePushBroadcastReceiver 55 | 56 | ```java 57 | PushBroadcastReceiverIml extends BasePushBroadcastReceiver{ 58 | 59 | public PushBroadcastReceiverIml() { 60 | } 61 | 62 | @Override 63 | public void onRegister(Context context, ReceiverInfo info) { 64 | Log.d(TAG, "推送注册成功\n" + info.toString()); 65 | } 66 | 67 | @Override 68 | public void onAlias(Context context, ReceiverInfo info) { 69 | Log.d(TAG, "设置了别名\n" + info.toString()); 70 | } 71 | 72 | @Override 73 | public void onMessage(Context context, ReceiverInfo info) { 74 | Log.d(TAG, "收到自定义消息\n" + info.toString()); 75 | } 76 | 77 | @Override 78 | public void onNotification(Context context, ReceiverInfo info) { 79 | Log.d(TAG, "收到通知\n" + info.toString()); 80 | } 81 | 82 | @Override 83 | public void onOpened(Context context, ReceiverInfo info) { 84 | Log.d(TAG, "点击了通知\n" + info.toString()); 85 | } 86 | } 87 | ``` 88 | 89 | 在`manifest`里面注册广播接收器 90 | 91 | ```xml 92 | 93 | 96 | 97 | 98 | 99 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | ``` 109 | 110 | #### 4.2addPushReceiverListener() 111 | 112 | ```java 113 | PushTargetManager.getInstance().addPushReceiverListener("ml", 114 | new PushTargetManager.OnPushReceiverListener() { 115 | @Override 116 | public void onRegister(ReceiverInfo info) { 117 | Log.d(TAG, "注册成功\n" + info.toString()); 118 | } 119 | 120 | @Override 121 | public void onAlias(ReceiverInfo info) { 122 | Log.d(TAG, "设置了别名\n" + info.toString()); 123 | } 124 | 125 | @Override 126 | public void onMessage(ReceiverInfo info) { 127 | Log.d(TAG, "收到了自定义消息\n" + info.toString()); 128 | } 129 | 130 | @Override 131 | public void onNotification(ReceiverInfo info) { 132 | Log.d(TAG, "收到了通知\n" + info.toString()); 133 | } 134 | 135 | @Override 136 | public void onOpened(ReceiverInfo info) { 137 | Log.d(TAG, "点击通知\n" + info.toString()); 138 | } 139 | }); 140 | ``` 141 | 142 | **注意**:*使用这种方式有一个局限,就是只会在应用运行期间有回调,应用杀死之后就不会有反应了,所以推荐使用第一种方式。* 143 | 144 | ### 5.处理用户点击通知栏 145 | 146 | 针对用户点击通知栏的行为,我们可能需要对通知进行处理跳转到指定的页面。当有用户点击通知栏的时候`BasePushBroadcastReceiver`或者`OnPushReceiverListener`的`onOpened(Context context, ReceiverInfo info)`会执行,我们只需要在这里处理就可以了。**需要注意的是,华为和OPPO的事件处理使用的是一个虚拟的Activity进行中转。 **因为无法监听到用户点击的事件,但是可以在点击之后打开的页面里面获取到传递的数据,间接的进行处理。所以使用的时候需要和后端协商好推送类型为自定义参数的格式。 147 | 148 | > OPPO和华为的处理Activity分别为`OppoLoadActivity`、`HuaweiLoadActivity`具体的intent设置请按照自己的需求修改。 149 | 150 | ![微信截图_20180530160745](img/微信截图_20180531111009.png) 151 | 152 | ### 6.设置别名 153 | 154 | 为了区别不同的设备与账号的对应关系,需要将设备别名设置到推送服务器和自己应用的服务器。* 当然,如果你不需要知道具体用户对于的设备,也可以不处理 *。 **别名的设置需要执行`PushTargetManager`的`setAlias`, **建议在注册成功之后再执行设置别名的操作,即在`HandleReceiverRegistration`的`handle`里面执行。 **需要注意的是华为推送不支持设置别名,只能获取华为服务器返回的`token` **。对于将别名上传到服务器的操作,用户只需要在`HandleReceiverAlias`类实现`handle`方法就可以了。 155 | 156 | ![微信截图_20180530152949](img/微信截图_20180531111115.png) 157 | 158 | ### 7.获取注册id 159 | 160 | 在`BasePushBroadcastReceiver`或者`OnPushReceiverListener`的`onRegister(Context context, ReceiverInfo info)`会在推送sdk注册成功之后回调,所以,可以在这里获取注册id,此时的`ReceiverInfo`数据结构如下: 161 | 162 | | pushTarget | PushTargetEnum的枚举,表示了当前的推送平台 | 163 | | ---------- | ------------------------------------------ | 164 | | title | 提示文本,例如“小米推送注册成功” | 165 | | content | 注册id | 166 | | rawData | 推送平台注册成功之后的原始返回值 | 167 | 168 | ## 模块设计思路 169 | 170 | 通过对推送服务的分析,我将推送分为了三个步骤,分别是:初始化、接收和处理,不同的推送平台的接收方式并不一样,但是推送服务只是一个工具,接收推送之后的处理才是关键,而这个是不需要根据不同的平台来变化的,所以我使用了一个统一的处理入口。 171 | 172 | ![PushMind](img/PushMind.png) 173 | 174 | 根据这个思路,我设计的代码结构如下: 175 | 176 | ![folder](img/folder.png) 177 | 178 | | 目录 | 说明 | 179 | | ------ | ---------------------------------- | 180 | | Handle | 统一处理接收到的推送信息 | 181 | | Target | 将不同的推送平台的初始化和接收存放在这个目录里面,按照推送平台分类。 | 182 | 183 | 关于消息的处理,通常会有:SDK注册成功、接收到消息、用户点击通知栏等,所以我将不同的动作分配到具体的类里面,减少一个大类处理多个方法的问题,通过一个入口类管理具体的行为。 -------------------------------------------------------------------------------- /push/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 87 | 88 | 89 | 90 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 197 | 198 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 210 | 211 | 216 | 220 | 223 | 224 | 225 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 238 | 239 | 240 | 241 | 242 | 243 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 260 | 261 | 264 | 265 | 266 | 267 | 268 | 271 | 272 | 273 | 274 | 278 | 279 | 280 | 283 | 284 | 286 | 291 | 292 | 294 | 299 | 300 | 301 | 302 | 303 | 310 | 313 | 314 | 315 | 316 | 323 | 326 | 327 | 328 | 329 | 334 | 337 | 338 | 339 | 340 | 345 | 348 | 349 | 350 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 381 | 382 | 383 | 384 | 385 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 397 | 398 | 399 | 400 | 401 | 402 | 405 | 406 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 433 | 434 | 437 | 438 | 439 | 440 | 443 | 444 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 460 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/OnTokenGetListener.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push; 2 | 3 | /** 4 | * 5 | */ 6 | public interface OnTokenGetListener { 7 | 8 | void onGetTokenSuccess(String bussid, String token); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/PushTargetManager.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push; 2 | 3 | import android.app.Application; 4 | 5 | import com.bearever.push.model.PushTargetEnum; 6 | import com.bearever.push.model.ReceiverInfo; 7 | import com.bearever.push.receiver.PushReceiverHandleManager; 8 | import com.bearever.push.target.BasePushTargetInit; 9 | import com.bearever.push.target.huawei.HuaweiInit; 10 | import com.bearever.push.target.jiguang.JPushInit; 11 | import com.bearever.push.target.meizu.MeizuInit; 12 | import com.bearever.push.target.oppo.OppoInit; 13 | import com.bearever.push.target.vivo.VivoInit; 14 | import com.bearever.push.target.xiaomi.XiaomiInit; 15 | 16 | /** 17 | * 初始化推送服务的管家,根据设备判断初始化哪个平台的推送服务; 18 | * ********* 19 | * 注册广播接收消息 20 | * 实现 {@link com.bearever.push.receiver.BasePushBroadcastReceiver} 类,在manifest里面添加如下代码实现广播的接收 21 | * 24 | * 25 | * 26 | * 29 | * 30 | * 31 | * 32 | * 33 | * 34 | * -------------------- 35 | * 另外一种是添加回调接口监听,执行{@link #addPushReceiverListener(String, OnPushReceiverListener)}添加推送回调接口 36 | * ********* 37 | * Created by luoming on 2018/5/28. 38 | */ 39 | public class PushTargetManager { 40 | private static final String TAG = "PushTargetManager"; 41 | private static PushTargetManager instance; 42 | /** 43 | * 当前的推送平台 44 | */ 45 | private PushTargetEnum mTarget = PushTargetEnum.XIAOMI; 46 | /** 47 | * 当前选择的推送方式 48 | */ 49 | private BasePushTargetInit mPushTarget; 50 | 51 | /** 52 | * 广播的action 53 | */ 54 | public static final String ACTION = "com.bearever.push.IPushBroadcast"; 55 | /** 56 | * 广播的permission 57 | */ 58 | public static final String PERMISSION = ".push.RECEIVER"; 59 | 60 | public static PushTargetManager getInstance() { 61 | if (instance == null) { 62 | synchronized (PushTargetManager.class) { 63 | if (instance == null) { 64 | instance = new PushTargetManager(); 65 | } 66 | } 67 | } 68 | return instance; 69 | } 70 | 71 | /** 72 | * 初始化 73 | * 74 | * @param context 75 | */ 76 | public PushTargetManager init(Application context) { 77 | String mobile_brand = android.os.Build.MANUFACTURER; 78 | mobile_brand = mobile_brand.toUpperCase(); 79 | //根据设备厂商选择推送平台 80 | //小米的使用小米推送,华为使用华为推送...其他的使用极光推送 81 | if (PushTargetEnum.XIAOMI.brand.equals(mobile_brand)) { 82 | this.mTarget = PushTargetEnum.XIAOMI; 83 | this.mPushTarget = new XiaomiInit(context); 84 | } else if (PushTargetEnum.HUAWEI.brand.equals(mobile_brand)) { 85 | this.mTarget = PushTargetEnum.HUAWEI; 86 | this.mPushTarget = new HuaweiInit(context); 87 | } else if (PushTargetEnum.OPPO.brand.equals(mobile_brand)) { 88 | this.mTarget = PushTargetEnum.OPPO; 89 | this.mPushTarget = new OppoInit(context); 90 | } else if (PushTargetEnum.VIVO.brand.equals(mobile_brand)) { 91 | this.mTarget = PushTargetEnum.VIVO; 92 | this.mPushTarget = new VivoInit(context); 93 | } else if (PushTargetEnum.MEIZU.brand.equals(mobile_brand)) { 94 | this.mTarget = PushTargetEnum.MEIZU; 95 | this.mPushTarget = new MeizuInit(context); 96 | } else { 97 | this.mTarget = PushTargetEnum.JPUSH; 98 | this.mPushTarget = new JPushInit(context); 99 | } 100 | PushReceiverHandleManager.getInstance().setPushTargetInit(mPushTarget); 101 | return this; 102 | } 103 | 104 | /** 105 | * 设置别名,华为不可用,需要通过@link 接口OnPushReceiverListener.onRegistration 方法回调取得 106 | * 107 | * @param alias 别名 108 | */ 109 | public PushTargetManager setAliasExceptHuawei(String alias) { 110 | if (mPushTarget == null) { 111 | throw new NullPointerException("请先执行init(),然后在设置别名"); 112 | } 113 | PushReceiverHandleManager.getInstance().setAlias(alias); 114 | return this; 115 | } 116 | 117 | /** 118 | * 添加推送监听 119 | * 120 | * @param key 121 | * @param listener 122 | */ 123 | public void addPushReceiverListener(String key, OnPushReceiverListener listener) { 124 | PushReceiverHandleManager.getInstance().addPushReceiverListener(key, listener); 125 | } 126 | 127 | /** 128 | * 移除一个推送监听 129 | * 130 | * @param key 131 | */ 132 | public void removePushReceiverListener(String key) { 133 | PushReceiverHandleManager.getInstance().removePushReceiverListener(key); 134 | } 135 | 136 | /** 137 | * 清空推送监听 138 | */ 139 | public void clearPushReceiverListener() { 140 | PushReceiverHandleManager.getInstance().clearPushReceiverListener(); 141 | 142 | } 143 | 144 | /** 145 | * 获取当前选择的推送平台 146 | * 147 | * @return 148 | */ 149 | public PushTargetEnum getPushTarget() { 150 | return this.mTarget; 151 | } 152 | 153 | public interface OnPushReceiverListener { 154 | /** 155 | * 注册成功回调 156 | * 157 | * @param info info.getContent() 对应的就是具体的推送平台的注册id ,例如小米的regid和华为的TMID 158 | */ 159 | void onRegister(ReceiverInfo info); 160 | 161 | /** 162 | * 别名设置完成回调 163 | * 164 | * @param info info.getContent() 对应的就是设置的别名 165 | */ 166 | void onAlias(ReceiverInfo info); 167 | 168 | /** 169 | * 收到穿透消息的回调 170 | * 171 | * @param info info.getContent对应的是消息文本 172 | */ 173 | void onMessage(ReceiverInfo info); 174 | 175 | /** 176 | * 收到通知的回调 177 | * 178 | * @param info info.getContent对应的是消息文本 179 | */ 180 | void onNotification(ReceiverInfo info); 181 | 182 | /** 183 | * 点击通知的回调 184 | * 185 | * @param info info.getContent对应的是消息文本 186 | */ 187 | void onOpened(ReceiverInfo info); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/model/PushTarget.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.model; 2 | 3 | /** 4 | * 推送平台 5 | * Created by luoming on 2018/5/31. 6 | */ 7 | 8 | public enum PushTarget { 9 | JPUSH, //极光 10 | 11 | XIAOMI, //小米 12 | 13 | HUAWEI,//华为 14 | 15 | OPPO,//oppo 16 | 17 | MEIZU; //魅族 18 | } 19 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/model/PushTargetEnum.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.model; 2 | 3 | /** 4 | * 推送平台 5 | * Created by luoming on 2018/5/31. 6 | */ 7 | 8 | public enum PushTargetEnum { 9 | /** 10 | * 极光 11 | */ 12 | JPUSH("JPUSH"), 13 | 14 | /** 15 | * 小米 16 | */ 17 | XIAOMI("XIAOMI"), 18 | 19 | /** 20 | * 华为 21 | */ 22 | HUAWEI("HUAWEI"), 23 | 24 | /** 25 | * OPPO 26 | */ 27 | OPPO("OPPO"), 28 | 29 | /** 30 | * 魅族 31 | */ 32 | MEIZU("MEIZU"), 33 | 34 | /** 35 | * VIVO 36 | */ 37 | VIVO("VIVO"); 38 | 39 | public String brand; 40 | 41 | PushTargetEnum(String brand) { 42 | this.brand = brand; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/model/ReceiverInfo.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 接收到的推送的消息 7 | * Created by luoming on 2018/5/28. 8 | */ 9 | public class ReceiverInfo implements Serializable { 10 | private PushTargetEnum pushTarget = PushTargetEnum.JPUSH; //推送平台 11 | private String title = ""; //标题 12 | private String content = ""; //内容 13 | private String extra = ""; //额外数据 14 | private Object rawData; //原始数据 15 | 16 | public ReceiverInfo() { 17 | } 18 | 19 | public ReceiverInfo(PushTargetEnum pushTarget, String title, String content, String extra, 20 | Object rawData) { 21 | this.pushTarget = pushTarget; 22 | this.title = title; 23 | this.content = content; 24 | this.extra = extra; 25 | this.rawData = rawData; 26 | } 27 | 28 | public String getTitle() { 29 | return title; 30 | } 31 | 32 | public void setTitle(String title) { 33 | this.title = title; 34 | } 35 | 36 | public PushTargetEnum getPushTarget() { 37 | return pushTarget; 38 | } 39 | 40 | public void setPushTarget(PushTargetEnum pushTarget) { 41 | this.pushTarget = pushTarget; 42 | } 43 | 44 | public String getContent() { 45 | return content; 46 | } 47 | 48 | public void setContent(String content) { 49 | this.content = content; 50 | } 51 | 52 | public String getExtra() { 53 | return extra; 54 | } 55 | 56 | public void setExtra(String extra) { 57 | this.extra = extra; 58 | } 59 | 60 | public Object getRawData() { 61 | return rawData; 62 | } 63 | 64 | public void setRawData(Object rawData) { 65 | this.rawData = rawData; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "推送平台:" + getPushTarget().brand + "\ntitle:" + getTitle() + "\ncontent:" + getContent(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/receiver/BasePushBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.bearever.push.model.ReceiverInfo; 8 | import com.google.gson.Gson; 9 | 10 | /** 11 | * 推送集成聚合广播接收器 12 | * 13 | * @author : malong luomingbear@163.com 14 | * @date : 2019/4/18 15 | **/ 16 | public abstract class BasePushBroadcastReceiver extends BroadcastReceiver { 17 | public BasePushBroadcastReceiver() { 18 | } 19 | 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | if (intent == null) { 23 | return; 24 | } 25 | 26 | String json = intent.getStringExtra("receiverinfo"); 27 | ReceiverInfo info = new Gson().fromJson(json, ReceiverInfo.class); 28 | // 根据推送平台确定原始数据的类型 29 | // PushTargetEnum pushTargetEnum = (PushTargetEnum) intent.getSerializableExtra("pushTarget"); 30 | // switch (pushTargetEnum) { 31 | // case MEIZU: 32 | // 33 | // break; 34 | // case HUAWEI: 35 | // break; 36 | // case JPUSH: 37 | // break; 38 | // case OPPO: 39 | // break; 40 | // case VIVO: 41 | // break; 42 | // case XIAOMI: 43 | // break; 44 | // } 45 | int type = intent.getIntExtra("type", 0); 46 | switch (type) { 47 | case PushReceiverHandleManager.TYPE_REGISTRATION: 48 | onRegister(context, info); 49 | break; 50 | case PushReceiverHandleManager.TYPE_ALIAS: 51 | onAlias(context, info); 52 | break; 53 | case PushReceiverHandleManager.TYPE_NOTIFICATION: 54 | onNotification(context, info); 55 | break; 56 | case PushReceiverHandleManager.TYPE_MESSAGE: 57 | onMessage(context, info); 58 | break; 59 | case PushReceiverHandleManager.TYPE_OPEN: 60 | onOpened(context, info); 61 | break; 62 | default: 63 | break; 64 | } 65 | } 66 | 67 | /** 68 | * 注册成功回调 69 | * 70 | * @param info info.getContent() 对应的就是具体的推送平台的注册id ,例如小米的regid和华为的TMID 71 | */ 72 | public abstract void onRegister(Context context, ReceiverInfo info); 73 | 74 | /** 75 | * 别名设置完成回调 76 | * 77 | * @param info info.getContent() 对应的就是设置的别名 78 | */ 79 | public abstract void onAlias(Context context, ReceiverInfo info); 80 | 81 | /** 82 | * 收到穿透消息的回调 83 | * 84 | * @param info info.getContent对应的是消息文本 85 | */ 86 | public abstract void onMessage(Context context, ReceiverInfo info); 87 | 88 | /** 89 | * 收到通知的回调 90 | * 91 | * @param info info.getContent对应的是消息文本 92 | */ 93 | public abstract void onNotification(Context context, ReceiverInfo info); 94 | 95 | /** 96 | * 点击通知的回调 97 | * 98 | * @param info info.getContent对应的是消息文本 99 | */ 100 | public abstract void onOpened(Context context, ReceiverInfo info); 101 | } 102 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/receiver/PushReceiverHandleManager.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.receiver; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.pm.PackageManager; 7 | import android.content.pm.ResolveInfo; 8 | import android.os.Build; 9 | import android.text.TextUtils; 10 | import android.util.Log; 11 | 12 | import com.bearever.push.PushTargetManager; 13 | import com.bearever.push.model.ReceiverInfo; 14 | import com.bearever.push.target.BasePushTargetInit; 15 | import com.google.gson.Gson; 16 | 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | /** 22 | * 统一处理收到的推送 23 | * Created by luoming on 2018/5/28. 24 | */ 25 | public class PushReceiverHandleManager { 26 | private static final String TAG = "PushReceiverHandleManag"; 27 | private static PushReceiverHandleManager instance; 28 | 29 | private String mAlias = ""; 30 | private BasePushTargetInit mPushTargetInit; 31 | 32 | /** 33 | * 待处理的消息列表 34 | */ 35 | private HashMap mReceiverMap = new HashMap<>(); 36 | 37 | /** 38 | * 注册行为 39 | */ 40 | public static final int TYPE_REGISTRATION = 0; 41 | /** 42 | * 设置别名行为 43 | */ 44 | public static final int TYPE_ALIAS = TYPE_REGISTRATION + 1; 45 | /** 46 | * 收到自定义消息行为 47 | */ 48 | public static final int TYPE_MESSAGE = TYPE_ALIAS + 1; 49 | /** 50 | * 收到通知行为 51 | */ 52 | public static final int TYPE_NOTIFICATION = TYPE_MESSAGE + 1; 53 | /** 54 | * 点击通知行为 55 | */ 56 | public static final int TYPE_OPEN = TYPE_NOTIFICATION + 1; 57 | 58 | public static PushReceiverHandleManager getInstance() { 59 | if (instance == null) { 60 | synchronized (PushReceiverHandleManager.class) { 61 | if (instance == null) { 62 | instance = new PushReceiverHandleManager(); 63 | } 64 | } 65 | } 66 | return instance; 67 | } 68 | 69 | private PushReceiverHandleManager() { 70 | 71 | } 72 | 73 | public void setPushTargetInit(BasePushTargetInit pushTargetInit) { 74 | this.mPushTargetInit = pushTargetInit; 75 | } 76 | 77 | /** 78 | * 发送广播 79 | * 80 | * @param context 81 | * @param type 行为类型 82 | * @param info 83 | */ 84 | private void sendBroadcast(Context context, int type, ReceiverInfo info) { 85 | Log.d(TAG, "发送广播\nPackageName:" + context.getPackageName() + "\n" + info.toString()); 86 | Intent intent = new Intent(); 87 | intent.putExtra("receiverinfo", new Gson().toJson(info)); 88 | intent.putExtra("type", type); 89 | intent.putExtra("pushTarget", info.getPushTarget()); 90 | intent.setAction(PushTargetManager.ACTION); 91 | 92 | //Android O 之后限制了隐式广播的接收,需要主动注册接收器 93 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { 94 | context.sendBroadcast(intent, context.getPackageName() + PushTargetManager.PERMISSION); 95 | } else { 96 | sendImplicitBroadcast(context, intent); 97 | } 98 | } 99 | 100 | /** 101 | * 发送隐式广播 102 | * 103 | * @param ctxt 104 | * @param i 105 | */ 106 | private static void sendImplicitBroadcast(Context ctxt, Intent i) { 107 | PackageManager pm = ctxt.getPackageManager(); 108 | List matches = pm.queryBroadcastReceivers(i, 0); 109 | 110 | for (ResolveInfo resolveInfo : matches) { 111 | Intent explicit = new Intent(i); 112 | ComponentName cn = 113 | new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName, 114 | resolveInfo.activityInfo.name); 115 | explicit.setPackage(resolveInfo.activityInfo.applicationInfo.packageName); 116 | explicit.setComponent(cn); 117 | ctxt.sendBroadcast(explicit, ctxt.getPackageName() + PushTargetManager.PERMISSION); 118 | } 119 | } 120 | 121 | /*** 122 | * 用户注册sdk之后的通知 123 | * 注册成功之后设置别名 124 | * @param context 125 | */ 126 | public void onRegistration(Context context, ReceiverInfo info) { 127 | for (Map.Entry item : mReceiverMap.entrySet()) { 128 | PushTargetManager.OnPushReceiverListener listener = item.getValue(); 129 | if (listener != null) { 130 | listener.onRegister(info); 131 | } 132 | } 133 | 134 | //执行设置别名操作 135 | doSetAlias(context, info); 136 | 137 | //发送广播 138 | sendBroadcast(context, TYPE_REGISTRATION, info); 139 | } 140 | 141 | /** 142 | * 执行别名设置 143 | */ 144 | private void doSetAlias(Context context, ReceiverInfo registerInfo) { 145 | if (TextUtils.isEmpty(mAlias) || mPushTargetInit == null) { 146 | return; 147 | } 148 | mPushTargetInit.setAlias(context, mAlias, registerInfo); 149 | } 150 | 151 | /** 152 | * 设置了别名之后 153 | * 154 | * @param context 155 | * @param info 156 | */ 157 | public void onAliasSet(Context context, ReceiverInfo info) { 158 | for (Map.Entry item : mReceiverMap.entrySet()) { 159 | PushTargetManager.OnPushReceiverListener listener = item.getValue(); 160 | if (listener != null) { 161 | listener.onAlias(info); 162 | } 163 | } 164 | 165 | //发送广播 166 | sendBroadcast(context, TYPE_ALIAS, info); 167 | } 168 | 169 | /** 170 | * 接收到消息推送,不会主动显示在通知栏 171 | * 172 | * @param context 173 | * @param info 174 | */ 175 | public void onMessageReceived(Context context, ReceiverInfo info) { 176 | for (Map.Entry item : mReceiverMap.entrySet()) { 177 | PushTargetManager.OnPushReceiverListener listener = item.getValue(); 178 | if (listener != null) { 179 | listener.onMessage(info); 180 | } 181 | } 182 | 183 | //发送广播 184 | sendBroadcast(context, TYPE_MESSAGE, info); 185 | } 186 | 187 | /** 188 | * 接收到通知,会主动显示在通知栏的 189 | * 190 | * @param context 191 | * @param info 192 | */ 193 | public void onNotificationReceived(Context context, ReceiverInfo info) { 194 | for (Map.Entry item : mReceiverMap.entrySet()) { 195 | PushTargetManager.OnPushReceiverListener listener = item.getValue(); 196 | if (listener != null) { 197 | listener.onNotification(info); 198 | } 199 | } 200 | 201 | //发送广播 202 | sendBroadcast(context, TYPE_NOTIFICATION, info); 203 | } 204 | 205 | /** 206 | * 用户点击了通知 207 | * 208 | * @param context 209 | * @param info 210 | */ 211 | public void onNotificationOpened(Context context, ReceiverInfo info) { 212 | for (Map.Entry item : mReceiverMap.entrySet()) { 213 | PushTargetManager.OnPushReceiverListener listener = item.getValue(); 214 | if (listener != null) { 215 | listener.onOpened(info); 216 | } 217 | } 218 | 219 | //发送广播 220 | sendBroadcast(context, TYPE_OPEN, info); 221 | } 222 | 223 | /** 224 | * 添加推送监听 225 | * 226 | * @param key 227 | * @param listener 228 | */ 229 | public void addPushReceiverListener(String key, PushTargetManager.OnPushReceiverListener listener) { 230 | mReceiverMap.put(key, listener); 231 | } 232 | 233 | /** 234 | * 移除一个推送监听 235 | * 236 | * @param key 237 | */ 238 | public void removePushReceiverListener(String key) { 239 | if (mReceiverMap.containsKey(key)) { 240 | mReceiverMap.remove(key); 241 | } 242 | } 243 | 244 | /** 245 | * 清空推送监听 246 | */ 247 | public void clearPushReceiverListener() { 248 | mReceiverMap.clear(); 249 | } 250 | 251 | public String getAlias() { 252 | return mAlias; 253 | } 254 | 255 | /** 256 | * 设置别名 257 | * 对于华为手机无效,华为手机只能通过返回的token识别用户 258 | * 259 | * @param mAlias 260 | */ 261 | public void setAlias(String mAlias) { 262 | this.mAlias = mAlias; 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/BasePushTargetInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | import com.bearever.push.model.ReceiverInfo; 7 | 8 | /** 9 | * 初始化推送平台的基类 10 | * Created by luoming on 2018/5/28. 11 | */ 12 | 13 | public abstract class BasePushTargetInit { 14 | protected static int MAX_RETRY_COUNT = 3; 15 | protected Application mApplication; 16 | protected String mAlias; 17 | 18 | /** 19 | * 推送初始化 20 | * 21 | * @param application 22 | */ 23 | public BasePushTargetInit(Application application) { 24 | this.mApplication = application; 25 | } 26 | 27 | /** 28 | * 设置别名 29 | * 30 | * @param context 31 | * @param alias 32 | */ 33 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 34 | this.mAlias = alias; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/huawei/HuaweiInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.huawei; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import android.util.Log; 7 | 8 | import com.bearever.push.model.ReceiverInfo; 9 | import com.bearever.push.target.BasePushTargetInit; 10 | import com.huawei.android.hms.agent.HMSAgent; 11 | 12 | /** 13 | * 华为推送初始化 14 | * Created by luoming on 2018/5/28. 15 | */ 16 | 17 | public class HuaweiInit extends BasePushTargetInit { 18 | private static final String TAG = "HuaweiInit"; 19 | private int mCount = 0; 20 | private Runnable mRunnable = new Runnable() { 21 | @Override 22 | public void run() { 23 | if (mCount < MAX_RETRY_COUNT) { 24 | init(); 25 | } 26 | mCount++; 27 | } 28 | }; 29 | 30 | private Handler mHandler; 31 | 32 | public HuaweiInit(Application application) { 33 | super(application); 34 | init(); 35 | Log.d(TAG, "初始化华为推送"); 36 | 37 | } 38 | 39 | private void init() { 40 | if (!HMSAgent.init(mApplication)) { 41 | if (mHandler == null) { 42 | mHandler = new Handler(); 43 | } 44 | mHandler.postDelayed(mRunnable, 1000); 45 | } 46 | } 47 | 48 | @Override 49 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 50 | //华为没有设置alias的功能 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/huawei/HuaweiLoadActivity.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.huawei; 2 | 3 | import android.net.Uri; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | 8 | import com.bearever.push.receiver.PushReceiverHandleManager; 9 | import com.bearever.push.model.PushTargetEnum; 10 | import com.bearever.push.model.ReceiverInfo; 11 | 12 | /** 13 | * 处理华为推送点击事件 14 | * 需要与后端协商好数据结构 15 | * scheme :ipush://router/huawei 16 | * 作者:luoming on 2018/10/13. 17 | * 邮箱:luomingbear@163.com 18 | * 版本:v1.0 19 | */ 20 | public class HuaweiLoadActivity extends AppCompatActivity { 21 | private static final String TAG = "HuaweiLoadActivity"; 22 | 23 | @Override 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | Uri uri = getIntent().getData(); 27 | String data = ""; 28 | // TODO: 2018/10/15 与后端协商好数据结构,这里的“data”是与后端协商的key 29 | if (uri != null) { 30 | data = uri.getQueryParameter("data"); 31 | } 32 | ReceiverInfo openInfo = new ReceiverInfo(); 33 | openInfo.setPushTarget(PushTargetEnum.HUAWEI); 34 | openInfo.setExtra(data); 35 | PushReceiverHandleManager.getInstance().onNotificationOpened(this, openInfo); 36 | finish(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/huawei/HuaweiPushBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.huawei; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | 7 | import com.bearever.push.PushTargetManager; 8 | import com.bearever.push.receiver.PushReceiverHandleManager; 9 | import com.bearever.push.model.PushTargetEnum; 10 | import com.bearever.push.model.ReceiverInfo; 11 | import com.huawei.hms.support.api.push.PushReceiver; 12 | 13 | /** 14 | * 自定义的华为推送服务的接收器 15 | * Created by luoming on 2018/5/29. 16 | */ 17 | 18 | public class HuaweiPushBroadcastReceiver extends PushReceiver { 19 | 20 | /** 21 | * token获取完成;token用于标识设备 22 | * 23 | * @param context 24 | * @param token 25 | * @param extras 26 | */ 27 | @Override 28 | public void onToken(Context context, String token, Bundle extras) { 29 | //获取token成功,token用于标识设备的唯一性 30 | ReceiverInfo alias = createReceiverInfo(); 31 | alias.setContent(token); 32 | alias.setRawData(extras); 33 | PushReceiverHandleManager.getInstance().onRegistration(context, alias); 34 | PushReceiverHandleManager.getInstance().onAliasSet(context, alias); 35 | Log.e("华为token", token + " -----------------------"); 36 | } 37 | 38 | /** 39 | * 接收到了穿透消息 40 | * 41 | * @param context 42 | * @param msg 43 | * @param bundle 44 | * @return 45 | */ 46 | @Override 47 | public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) { 48 | try { 49 | //CP可以自己解析消息内容,然后做相应的处理 50 | String content = new String(msg, "UTF-8"); 51 | ReceiverInfo info = createReceiverInfo(); 52 | info.setContent(content); 53 | info.setRawData(bundle); 54 | PushReceiverHandleManager.getInstance().onMessageReceived(context, info); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | return false; 59 | } 60 | 61 | /** 62 | * 点击通知栏事件处理 63 | * 64 | * @param context 65 | * @param event 66 | * @param extras 67 | */ 68 | @Override 69 | public void onEvent(Context context, Event event, Bundle extras) { 70 | //点击通知事件 71 | if (Event.NOTIFICATION_OPENED.equals(event)) { 72 | ReceiverInfo info = createReceiverInfo(); 73 | String message = extras.getString(BOUND_KEY.pushMsgKey); 74 | info.setContent(message); 75 | info.setRawData(extras); 76 | PushReceiverHandleManager.getInstance().onNotificationOpened(context, info); 77 | } 78 | } 79 | 80 | /** 81 | * SDK状态 82 | * 83 | * @param context 84 | * @param pushState 85 | */ 86 | @Override 87 | public void onPushState(Context context, boolean pushState) { 88 | // if (pushState) { 89 | // ReceiverInfo info = createReceiverInfo(); 90 | // info.setTitle("华为推送注册成功"); 91 | // PushReceiverHandleManager.getInstance().onRegistration(context, info); 92 | // } 93 | } 94 | 95 | private ReceiverInfo createReceiverInfo() { 96 | ReceiverInfo info = new ReceiverInfo(); 97 | info.setPushTarget(PushTargetEnum.HUAWEI); 98 | return info; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/jiguang/IJPushEventReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.jiguang; 2 | 3 | import android.content.Context; 4 | 5 | import com.bearever.push.model.PushTargetEnum; 6 | import com.bearever.push.model.ReceiverInfo; 7 | import com.bearever.push.receiver.PushReceiverHandleManager; 8 | 9 | import cn.jpush.android.api.JPushMessage; 10 | import cn.jpush.android.service.JPushMessageReceiver; 11 | 12 | /** 13 | * 自定义的alin/tag设置接口回调 14 | * Created by luoming on 2018/5/28. 15 | */ 16 | 17 | public class IJPushEventReceiver extends JPushMessageReceiver { 18 | private static final String TAG = "IJPushEventReceiver"; 19 | 20 | @Override 21 | public void onTagOperatorResult(Context var1, JPushMessage var2) { 22 | } 23 | 24 | @Override 25 | public void onCheckTagOperatorResult(Context var1, JPushMessage var2) { 26 | 27 | } 28 | 29 | @Override 30 | public void onAliasOperatorResult(Context var1, JPushMessage var2) { 31 | ReceiverInfo aliasInfo = new ReceiverInfo(); 32 | aliasInfo.setContent(var2.getAlias()); 33 | aliasInfo.setPushTarget(PushTargetEnum.JPUSH); 34 | aliasInfo.setRawData(var2); 35 | PushReceiverHandleManager.getInstance().onAliasSet(var1, aliasInfo); 36 | } 37 | 38 | @Override 39 | public void onMobileNumberOperatorResult(Context var1, JPushMessage var2) { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/jiguang/JPushBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.jiguang; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | 9 | import com.bearever.push.receiver.PushReceiverHandleManager; 10 | import com.bearever.push.model.PushTargetEnum; 11 | import com.bearever.push.model.ReceiverInfo; 12 | 13 | import cn.jpush.android.api.JPushInterface; 14 | 15 | /** 16 | * 自定义的极光推送接收 17 | * Created by luoming on 2018/5/28. 18 | */ 19 | 20 | public class JPushBroadcastReceiver extends BroadcastReceiver { 21 | 22 | @Override 23 | public void onReceive(Context context, Intent intent) { 24 | if (intent == null) { 25 | return; 26 | } 27 | 28 | String action = intent.getAction(); 29 | if (TextUtils.isEmpty(action)) { 30 | return; 31 | } 32 | 33 | if (JPushInterface.ACTION_REGISTRATION_ID.equals(action)) { 34 | //用户注册SDK的intent 35 | ReceiverInfo info = new ReceiverInfo(); 36 | info.setPushTarget(PushTargetEnum.JPUSH); 37 | info.setRawData(intent); 38 | Bundle bundle = intent.getExtras(); 39 | if (bundle != null) { 40 | String code = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID, ""); 41 | info.setContent(code); 42 | } 43 | info.setTitle("极光推送注册成功"); 44 | PushReceiverHandleManager.getInstance().onRegistration(context, info); 45 | } else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) { 46 | //用户接收SDK消息的intent 47 | PushReceiverHandleManager.getInstance().onMessageReceived(context, convert2MessageReceiverInfo(intent)); 48 | } else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) { 49 | //用户接收SDK通知栏信息的intent 50 | PushReceiverHandleManager.getInstance().onNotificationReceived(context, convert2NotificationReceiverInfo(intent)); 51 | } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) { 52 | //用户打开自定义通知栏的intent 53 | PushReceiverHandleManager.getInstance().onNotificationOpened(context, convert2NotificationReceiverInfo(intent)); 54 | } 55 | } 56 | 57 | /** 58 | * 将intent的数据转化为ReceiverInfo用于处理 59 | * 60 | * @param intent 61 | * @return 62 | */ 63 | private ReceiverInfo convert2NotificationReceiverInfo(Intent intent) { 64 | ReceiverInfo info = new ReceiverInfo(); 65 | Bundle bundle = intent.getExtras(); 66 | String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE); 67 | String message = bundle.getString(JPushInterface.EXTRA_ALERT); 68 | String extras = bundle.getString(JPushInterface.EXTRA_EXTRA); 69 | 70 | info.setTitle(title); 71 | info.setContent(message); 72 | info.setExtra(extras); 73 | info.setPushTarget(PushTargetEnum.JPUSH); 74 | info.setRawData(intent); 75 | return info; 76 | } 77 | 78 | /** 79 | * 将intent的数据转化为ReceiverInfo用于处理 80 | * 81 | * @param intent 82 | * @return 83 | */ 84 | private ReceiverInfo convert2MessageReceiverInfo(Intent intent) { 85 | ReceiverInfo info = new ReceiverInfo(); 86 | Bundle bundle = intent.getExtras(); 87 | String title = bundle.getString(JPushInterface.EXTRA_TITLE); 88 | String message = bundle.getString(JPushInterface.EXTRA_MESSAGE); 89 | String extras = bundle.getString(JPushInterface.EXTRA_EXTRA); 90 | 91 | info.setTitle(title); 92 | info.setContent(message); 93 | info.setExtra(extras); 94 | info.setPushTarget(PushTargetEnum.JPUSH); 95 | info.setRawData(intent); 96 | return info; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/jiguang/JPushInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.jiguang; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.util.Log; 6 | 7 | import com.bearever.push.model.ReceiverInfo; 8 | import com.bearever.push.target.BasePushTargetInit; 9 | 10 | import cn.jpush.android.api.JPushInterface; 11 | 12 | /** 13 | * 极光推送的初始化服务 14 | * Created by luoming on 2018/5/28. 15 | */ 16 | 17 | public class JPushInit extends BasePushTargetInit { 18 | private static final String TAG = "JPushInit"; 19 | 20 | public JPushInit(Application application) { 21 | super(application); 22 | JPushInterface.init(application); 23 | Log.d(TAG, "初始化极光推送"); 24 | } 25 | 26 | @Override 27 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 28 | JPushInterface.setAlias(context, 0, alias); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/meizu/MeizuInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.meizu; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.text.TextUtils; 6 | import android.util.Log; 7 | 8 | import com.bearever.push.model.ReceiverInfo; 9 | import com.bearever.push.target.BasePushTargetInit; 10 | import com.bearever.push.util.ApplicationUtil; 11 | import com.meizu.cloud.pushsdk.PushManager; 12 | 13 | /** 14 | * 魅族推送的初始化 15 | * 作者:luoming on 2018/9/30. 16 | * 邮箱:luomingbear@163.com 17 | * 版本:v1.0 18 | */ 19 | public class MeizuInit extends BasePushTargetInit { 20 | private static final String TAG = "MeizuInit"; 21 | 22 | public MeizuInit(Application application) { 23 | super(application); 24 | 25 | String appid = ApplicationUtil.getMetaData(application, "MEIZU_APP_ID"); 26 | appid = appid.replace(" ", ""); 27 | String appkey = ApplicationUtil.getMetaData(application, "MEIZU_APP_KEY"); 28 | if (TextUtils.isEmpty(appid) || TextUtils.isEmpty(appkey)) { 29 | return; 30 | } 31 | 32 | PushManager.register(application, appid, appkey); 33 | Log.d(TAG, "初始化魅族推送"); 34 | } 35 | 36 | /** 37 | * 魅族设置别名需要pushId,所以不能直接设置,需要在注册成功之后执行设置别名 38 | * 这里的设置功能不可用 39 | * 40 | * @param context 41 | * @param alias 42 | */ 43 | @Override 44 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 45 | super.setAlias(context, alias, registerInfo); 46 | String appid = ApplicationUtil.getMetaData(context, "MEIZU_APP_ID"); 47 | appid = appid.replace(" ", ""); 48 | String appkey = ApplicationUtil.getMetaData(context, "MEIZU_APP_KEY"); 49 | PushManager.subScribeAlias(context, appid, appkey, registerInfo.getContent(), alias); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/meizu/MeizuMessageReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.meizu; 2 | 3 | import android.content.Context; 4 | 5 | import com.bearever.push.receiver.PushReceiverHandleManager; 6 | import com.bearever.push.model.PushTargetEnum; 7 | import com.bearever.push.model.ReceiverInfo; 8 | import com.meizu.cloud.pushsdk.MzPushMessageReceiver; 9 | import com.meizu.cloud.pushsdk.handler.MzPushMessage; 10 | import com.meizu.cloud.pushsdk.platform.message.PushSwitchStatus; 11 | import com.meizu.cloud.pushsdk.platform.message.RegisterStatus; 12 | import com.meizu.cloud.pushsdk.platform.message.SubAliasStatus; 13 | import com.meizu.cloud.pushsdk.platform.message.SubTagsStatus; 14 | import com.meizu.cloud.pushsdk.platform.message.UnRegisterStatus; 15 | 16 | /** 17 | * 魅族消息的接收 18 | * 作者:luoming on 2018/10/8. 19 | * 邮箱:luomingbear@163.com 20 | * 版本:v1.0 21 | */ 22 | public class MeizuMessageReceiver extends MzPushMessageReceiver { 23 | @Override 24 | @Deprecated 25 | public void onRegister(Context context, String pushid) { 26 | //调用 PushManager.register(context)方法后,会在此回调注册状态 27 | //应用在接受返回的 pushid 28 | } 29 | 30 | @Override 31 | public void onMessage(Context context, String s) { 32 | //接收服务器推送的透传消息 33 | ReceiverInfo info = new ReceiverInfo(); 34 | info.setPushTarget(PushTargetEnum.MEIZU); 35 | info.setContent(s); 36 | PushReceiverHandleManager.getInstance().onMessageReceived(context, info); 37 | } 38 | 39 | @Override 40 | @Deprecated 41 | public void onUnRegister(Context context, boolean b) { 42 | //调用 PushManager.unRegister(context)方法后,会在此回调反注册状态 43 | } 44 | 45 | @Override 46 | public void onPushStatus(Context context, PushSwitchStatus 47 | pushSwitchStatus) { 48 | //检查通知栏和透传消息开关状态回调 49 | } 50 | 51 | @Override 52 | public void onRegisterStatus(Context context, RegisterStatus registerStatus) { 53 | //调用新版订阅 PushManager.register(context,appId,appKey)回调 54 | if (registerStatus.code.equals(RegisterStatus.SUCCESS_CODE)) { 55 | ReceiverInfo info = new ReceiverInfo(); 56 | info.setPushTarget(PushTargetEnum.MEIZU); 57 | info.setTitle("魅族推送注册成功"); 58 | info.setContent(registerStatus.getPushId()); 59 | info.setRawData(registerStatus); 60 | PushReceiverHandleManager.getInstance().onRegistration(context, info); 61 | } 62 | } 63 | 64 | @Override 65 | public void onUnRegisterStatus(Context context, UnRegisterStatus unRegisterStatus) { 66 | //新版反订阅回调 67 | } 68 | 69 | @Override 70 | public void onSubTagsStatus(Context context, SubTagsStatus subTagsStatus) { 71 | //标签回调 72 | } 73 | 74 | @Override 75 | public void onSubAliasStatus(Context context, SubAliasStatus subAliasStatus) { 76 | //别名回调 77 | ReceiverInfo info = new ReceiverInfo(); 78 | info.setPushTarget(PushTargetEnum.MEIZU); 79 | info.setContent(subAliasStatus.getAlias()); 80 | info.setRawData(subAliasStatus); 81 | PushReceiverHandleManager.getInstance().onAliasSet(context, info); 82 | } 83 | 84 | @Override 85 | public void onNotificationArrived(Context context, MzPushMessage mzPushMessage) { 86 | //通知栏消息到达回调,flyme6 基于 android6.0 以上不再回调 87 | PushReceiverHandleManager.getInstance().onNotificationReceived(context, createReceiverInfo(mzPushMessage)); 88 | } 89 | 90 | @Override 91 | public void onNotificationClicked(Context context, MzPushMessage mzPushMessage) { 92 | //通知栏消息点击回调 93 | PushReceiverHandleManager.getInstance().onNotificationOpened(context, createReceiverInfo(mzPushMessage)); 94 | } 95 | 96 | @Override 97 | public void onNotificationDeleted(Context context, MzPushMessage mzPushMessage) { 98 | //通知栏消息删除回调;flyme6 基于 android6.0 以上不再回调 99 | } 100 | 101 | private ReceiverInfo createReceiverInfo(MzPushMessage mzPushMessage) { 102 | ReceiverInfo info = new ReceiverInfo(); 103 | info.setPushTarget(PushTargetEnum.MEIZU); 104 | info.setContent(mzPushMessage.getContent()); 105 | info.setTitle(mzPushMessage.getTitle()); 106 | info.setExtra(mzPushMessage.getSelfDefineContentString()); 107 | info.setRawData(mzPushMessage); 108 | return info; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/oppo/OppoInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.oppo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import android.util.Log; 7 | 8 | import com.bearever.push.model.PushTargetEnum; 9 | import com.bearever.push.model.ReceiverInfo; 10 | import com.bearever.push.receiver.PushReceiverHandleManager; 11 | import com.bearever.push.target.BasePushTargetInit; 12 | import com.bearever.push.util.ApplicationUtil; 13 | import com.coloros.mcssdk.PushManager; 14 | import com.coloros.mcssdk.callback.PushCallback; 15 | import com.coloros.mcssdk.mode.ErrorCode; 16 | import com.coloros.mcssdk.mode.SubscribeResult; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * oppo的推送服务初始化 22 | * 作者:luoming on 2018/9/30. 23 | * 邮箱:luomingbear@163.com 24 | * 版本:v1.0 25 | */ 26 | public class OppoInit extends BasePushTargetInit { 27 | private static final String TAG = "OppoInit"; 28 | private int mInitCount = 0; 29 | private int mAliasCount = 0; 30 | private Handler mHandler; 31 | 32 | private Runnable mInitRunnable = new Runnable() { 33 | @Override 34 | public void run() { 35 | if (mInitCount < MAX_RETRY_COUNT) { 36 | init(); 37 | mInitCount++; 38 | } 39 | } 40 | }; 41 | 42 | private Runnable mAliasRunnable = new Runnable() { 43 | @Override 44 | public void run() { 45 | if (mAliasCount < MAX_RETRY_COUNT) { 46 | setAlias(mApplication, mAlias, null); 47 | mAliasCount++; 48 | } 49 | } 50 | }; 51 | 52 | public OppoInit(Application application) { 53 | super(application); 54 | if (!PushManager.isSupportPush(application)) { 55 | return; 56 | } 57 | init(); 58 | Log.d(TAG, "初始化OPPO推送"); 59 | } 60 | 61 | private void init() { 62 | String appKey = ApplicationUtil.getMetaData(mApplication, "OPPO_APP_KEY"); 63 | String appSecret = ApplicationUtil.getMetaData(mApplication, "OPPO_APP_SECRET"); 64 | PushManager.getInstance().register(mApplication, appKey, appSecret, pushCallback); 65 | } 66 | 67 | private PushCallback pushCallback = new PushCallback() { 68 | @Override 69 | public void onRegister(int i, String s) { 70 | //s 注册id,用来唯一标识设备的 71 | if (i == ErrorCode.SUCCESS) { 72 | //注册成功 73 | ReceiverInfo info = new ReceiverInfo(); 74 | info.setContent(s); 75 | info.setTitle("OPPO注册成功"); 76 | info.setRawData(s); 77 | info.setPushTarget(PushTargetEnum.OPPO); 78 | PushReceiverHandleManager.getInstance().onRegistration(mApplication, info); 79 | } else { 80 | if (mHandler == null) { 81 | mHandler = new Handler(); 82 | } 83 | mHandler.postDelayed(mInitRunnable, 1000); 84 | } 85 | } 86 | 87 | @Override 88 | public void onUnRegister(int i) { 89 | 90 | } 91 | 92 | @Override 93 | public void onGetAliases(int i, List list) { 94 | 95 | } 96 | 97 | @Override 98 | public void onSetAliases(int i, List list) { 99 | if (i == ErrorCode.SUCCESS) { 100 | //成功 101 | ReceiverInfo aliasInfo = new ReceiverInfo(); 102 | if (list != null && list.size() > 0) { 103 | aliasInfo.setContent(list.get(0).getContent()); 104 | } 105 | aliasInfo.setRawData(list); 106 | aliasInfo.setPushTarget(PushTargetEnum.OPPO); 107 | PushReceiverHandleManager.getInstance().onAliasSet(mApplication, aliasInfo); 108 | } else { 109 | if (mHandler == null) { 110 | mHandler = new Handler(); 111 | } 112 | mHandler.postDelayed(mAliasRunnable, 1000); 113 | } 114 | } 115 | 116 | @Override 117 | public void onUnsetAliases(int i, List list) { 118 | 119 | } 120 | 121 | @Override 122 | public void onSetUserAccounts(int i, List list) { 123 | 124 | } 125 | 126 | @Override 127 | public void onUnsetUserAccounts(int i, List list) { 128 | 129 | } 130 | 131 | @Override 132 | public void onGetUserAccounts(int i, List list) { 133 | 134 | } 135 | 136 | @Override 137 | public void onSetTags(int i, List list) { 138 | 139 | } 140 | 141 | @Override 142 | public void onUnsetTags(int i, List list) { 143 | 144 | } 145 | 146 | @Override 147 | public void onGetTags(int i, List list) { 148 | 149 | } 150 | 151 | @Override 152 | public void onGetPushStatus(int i, int i1) { 153 | 154 | } 155 | 156 | @Override 157 | public void onSetPushTime(int i, String s) { 158 | 159 | } 160 | 161 | @Override 162 | public void onGetNotificationStatus(int i, int i1) { 163 | 164 | } 165 | }; 166 | 167 | @Override 168 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 169 | super.setAlias(context, alias, registerInfo); 170 | // 别名设置总是失败,索性取消,使用注册id识别用户 171 | // List list = new ArrayList<>(); 172 | // list.add(alias); 173 | // PushManager.getInstance().setAliases(list); 174 | PushReceiverHandleManager.getInstance().onAliasSet(context, registerInfo); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/oppo/OppoLoadActivity.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.oppo; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import com.bearever.push.receiver.PushReceiverHandleManager; 8 | import com.bearever.push.model.PushTargetEnum; 9 | import com.bearever.push.model.ReceiverInfo; 10 | 11 | import java.util.Set; 12 | 13 | /** 14 | * 处理OPPO的通知栏点击事件 15 | * action:ipush.router.oppo 16 | * 作者:luoming on 2018/10/12. 17 | * 邮箱:luomingbear@163.com 18 | * 版本:v1.0 19 | */ 20 | public class OppoLoadActivity extends AppCompatActivity { 21 | private static final String TAG = "OppoLoadActivity"; 22 | 23 | @Override 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | //取出bundle里面的参数数据改为json格式 27 | Bundle bundle = getIntent().getExtras(); 28 | Set set = bundle.keySet(); 29 | StringBuffer sb = new StringBuffer(); 30 | if (set != null) { 31 | sb.append("{"); 32 | for (String key : set) { 33 | String vaues = bundle.getString(key); 34 | sb.append("\""); 35 | sb.append(key); 36 | sb.append("\""); 37 | sb.append(":"); 38 | sb.append("\""); 39 | sb.append(vaues); 40 | sb.append("\""); 41 | sb.append(","); 42 | } 43 | sb.append("}"); 44 | } 45 | //发送到处理中心 46 | ReceiverInfo openInfo = new ReceiverInfo(); 47 | openInfo.setPushTarget(PushTargetEnum.OPPO); 48 | openInfo.setExtra(sb.replace(sb.length() - 2, sb.length(), "}").toString()); 49 | PushReceiverHandleManager.getInstance().onNotificationOpened(this, openInfo); 50 | finish(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/oppo/OppoMessageService.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.oppo; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.bearever.push.receiver.PushReceiverHandleManager; 7 | import com.bearever.push.model.PushTargetEnum; 8 | import com.bearever.push.model.ReceiverInfo; 9 | import com.coloros.mcssdk.PushService; 10 | import com.coloros.mcssdk.mode.AppMessage; 11 | import com.coloros.mcssdk.mode.CommandMessage; 12 | import com.coloros.mcssdk.mode.SptDataMessage; 13 | 14 | /** 15 | * OPPO消息接收处理器 16 | * 作者:luoming on 2018/9/30. 17 | * 邮箱:luomingbear@163.com 18 | * 版本:v1.0 19 | */ 20 | public class OppoMessageService extends PushService { 21 | private static final String TAG = "OppoMessageService"; 22 | 23 | /** 24 | * 普通应用消息 25 | * 26 | * @param context 27 | * @param appMessage 28 | */ 29 | @Override 30 | public void processMessage(Context context, AppMessage appMessage) { 31 | super.processMessage(context, appMessage); 32 | Log.d(TAG, "app processMessage: handle:" + appMessage); 33 | ReceiverInfo info = new ReceiverInfo(); 34 | info.setTitle(appMessage.getTitle()); 35 | info.setContent(appMessage.getContent()); 36 | info.setPushTarget(PushTargetEnum.OPPO); 37 | info.setRawData(appMessage); 38 | PushReceiverHandleManager.getInstance().onNotificationReceived(context, info); 39 | } 40 | 41 | /** 42 | * 透传消息处理,应用可以打开页面或者执行命令,如果应用不需要处理透传消息,则不需要重写此方法 43 | * 44 | * @param context 45 | * @param sptDataMessage 46 | */ 47 | @Override 48 | public void processMessage(Context context, SptDataMessage sptDataMessage) { 49 | super.processMessage(context, sptDataMessage); 50 | Log.d(TAG, "spt processMessage: handle:" + sptDataMessage); 51 | ReceiverInfo info = new ReceiverInfo(); 52 | info.setContent(sptDataMessage.getContent()); 53 | info.setExtra(sptDataMessage.getDescription()); 54 | info.setPushTarget(PushTargetEnum.OPPO); 55 | info.setRawData(sptDataMessage); 56 | PushReceiverHandleManager.getInstance().onMessageReceived(context, info); 57 | } 58 | 59 | /** 60 | * 命令消息,主要是服务端对客户端调用的反馈,一般应用不需要重写此方法 61 | * 62 | * @param context 63 | * @param commandMessage 64 | */ 65 | @Override 66 | public void processMessage(Context context, CommandMessage commandMessage) { 67 | super.processMessage(context, commandMessage); 68 | Log.d(TAG, "command processMessage: " + commandMessage); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/vivo/VivoBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.vivo; 2 | 3 | import android.content.Context; 4 | 5 | import com.bearever.push.receiver.PushReceiverHandleManager; 6 | import com.bearever.push.model.PushTargetEnum; 7 | import com.bearever.push.model.ReceiverInfo; 8 | import com.vivo.push.model.UPSNotificationMessage; 9 | import com.vivo.push.sdk.OpenClientPushMessageReceiver; 10 | 11 | /** 12 | * desc: vivo的消息接收 13 | * auth: malong 14 | * email: luomingbear@163.com 15 | * time: 2019/4/18 16 | **/ 17 | public class VivoBroadcastReceiver extends OpenClientPushMessageReceiver { 18 | @Override 19 | public void onNotificationMessageClicked(Context context, UPSNotificationMessage upsNotificationMessage) { 20 | /** 21 | * UPSNotificationMessage 数据结构 22 | * msgid:通知 id 23 | * title:通知标题 24 | * content:通知内容 25 | * skipContent:通知自定义内容 26 | * params:自定义键值对 27 | */ 28 | 29 | ReceiverInfo info = new ReceiverInfo(); 30 | info.setTitle(upsNotificationMessage.getTitle()); 31 | info.setContent(upsNotificationMessage.getContent()); 32 | info.setPushTarget(PushTargetEnum.VIVO); 33 | info.setRawData(upsNotificationMessage); 34 | PushReceiverHandleManager.getInstance().onNotificationOpened(context, info); 35 | } 36 | 37 | @Override 38 | public void onReceiveRegId(Context context, String s) { 39 | ReceiverInfo info = new ReceiverInfo(); 40 | info.setTitle("VIVO推送初始化成功"); 41 | info.setContent(s); 42 | info.setPushTarget(PushTargetEnum.VIVO); 43 | info.setRawData(s); 44 | PushReceiverHandleManager.getInstance().onRegistration(context, info); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/vivo/VivoInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.vivo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import android.util.Log; 7 | 8 | import com.bearever.push.model.PushTargetEnum; 9 | import com.bearever.push.model.ReceiverInfo; 10 | import com.bearever.push.receiver.PushReceiverHandleManager; 11 | import com.bearever.push.target.BasePushTargetInit; 12 | import com.vivo.push.IPushActionListener; 13 | import com.vivo.push.PushClient; 14 | 15 | /** 16 | * desc: vivo推送初始化类 17 | * auth: malong 18 | * email: luomingbear@163.com 19 | * time: 2019/4/18 20 | **/ 21 | public class VivoInit extends BasePushTargetInit { 22 | private static final String TAG = "VivoInit"; 23 | private int mInitCount = 0; 24 | private int mAliasCount = 0; 25 | private Handler mHandler; 26 | 27 | public VivoInit(final Application application) { 28 | super(application); 29 | if (!PushClient.getInstance(application).isSupport()) { 30 | return; 31 | } 32 | 33 | //初始化 34 | PushClient.getInstance(application).initialize(); 35 | if (mHandler == null) { 36 | mHandler = new Handler(); 37 | } 38 | mHandler.post(initRunnable); 39 | Log.d(TAG, "初始化魅族推送"); 40 | } 41 | 42 | private Runnable initRunnable = new Runnable() { 43 | @Override 44 | public void run() { 45 | //打开推送 46 | PushClient.getInstance(mApplication).turnOnPush(new IPushActionListener() { 47 | @Override 48 | public void onStateChanged(int i) { 49 | if (i != 0 && i != 1) { 50 | //失败重试 51 | if (mInitCount < MAX_RETRY_COUNT) { 52 | if (mHandler == null) { 53 | mHandler = new Handler(); 54 | } 55 | mHandler.postDelayed(initRunnable, 1000); 56 | mInitCount++; 57 | } 58 | } 59 | } 60 | }); 61 | } 62 | }; 63 | 64 | @Override 65 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 66 | super.setAlias(context, alias, registerInfo); 67 | if (mHandler == null) { 68 | mHandler = new Handler(); 69 | } 70 | mHandler.post(aliasRunnable); 71 | } 72 | 73 | private Runnable aliasRunnable = new Runnable() { 74 | @Override 75 | public void run() { 76 | //设置别名 77 | PushClient.getInstance(mApplication).bindAlias(mAlias, new IPushActionListener() { 78 | @Override 79 | public void onStateChanged(int i) { 80 | if (i != 0 && i != 1) { 81 | //失败重试 82 | if (mAliasCount < MAX_RETRY_COUNT) { 83 | if (mHandler == null) { 84 | mHandler = new Handler(); 85 | } 86 | mHandler.postDelayed(aliasRunnable, 1000); 87 | mAliasCount++; 88 | } 89 | } else { 90 | //成功 91 | ReceiverInfo info = new ReceiverInfo(); 92 | info.setContent(mAlias); 93 | info.setPushTarget(PushTargetEnum.VIVO); 94 | PushReceiverHandleManager.getInstance().onAliasSet(mApplication, info); 95 | } 96 | } 97 | }); 98 | } 99 | }; 100 | 101 | } 102 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/xiaomi/XiaomiBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.xiaomi; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.bearever.push.model.PushTargetEnum; 7 | import com.bearever.push.model.ReceiverInfo; 8 | import com.bearever.push.receiver.PushReceiverHandleManager; 9 | import com.google.gson.Gson; 10 | import com.xiaomi.mipush.sdk.MiPushClient; 11 | import com.xiaomi.mipush.sdk.MiPushCommandMessage; 12 | import com.xiaomi.mipush.sdk.MiPushMessage; 13 | import com.xiaomi.mipush.sdk.PushMessageReceiver; 14 | 15 | /** 16 | * 自定义的小米推送接收 17 | * Created by luoming on 2018/5/28. 18 | */ 19 | 20 | public class XiaomiBroadcastReceiver extends PushMessageReceiver { 21 | @Override 22 | public void onReceivePassThroughMessage(Context var1, MiPushMessage var2) { 23 | PushReceiverHandleManager.getInstance().onMessageReceived(var1, convert2ReceiverInfo(var2)); 24 | } 25 | 26 | @Override 27 | public void onNotificationMessageClicked(Context var1, MiPushMessage var2) { 28 | PushReceiverHandleManager.getInstance().onNotificationOpened(var1, convert2ReceiverInfo(var2)); 29 | } 30 | 31 | @Override 32 | public void onNotificationMessageArrived(Context var1, MiPushMessage var2) { 33 | Log.e("接收消息成功", "------------------------"); 34 | PushReceiverHandleManager.getInstance().onNotificationReceived(var1, convert2ReceiverInfo(var2)); 35 | } 36 | 37 | @Override 38 | public void onReceiveRegisterResult(Context var1, MiPushCommandMessage command) { 39 | if (MiPushClient.COMMAND_REGISTER.equals(command.getCommand())) { 40 | ReceiverInfo info = convert2ReceiverInfo(command); 41 | info.setTitle("小米推送注册成功"); 42 | //注册id 43 | String id = command.getCommandArguments().get(0); 44 | info.setContent(id); 45 | Log.e("command id", id); 46 | PushReceiverHandleManager.getInstance().onRegistration(var1, info); 47 | } 48 | } 49 | 50 | /** 51 | * 将intent的数据转化为ReceiverInfo用于处理 52 | * 53 | * @param miPushMessage 54 | * @return 55 | */ 56 | private ReceiverInfo convert2ReceiverInfo(MiPushMessage miPushMessage) { 57 | ReceiverInfo info = new ReceiverInfo(); 58 | info.setContent(miPushMessage.getContent()); 59 | info.setPushTarget(PushTargetEnum.XIAOMI); 60 | info.setTitle(miPushMessage.getTitle()); 61 | info.setRawData(miPushMessage); 62 | if (miPushMessage.getExtra() != null) { 63 | info.setExtra(new Gson().toJson(miPushMessage.getExtra())); 64 | } 65 | return info; 66 | } 67 | 68 | /** 69 | * 将intent的数据转化为ReceiverInfo用于处理 70 | * 71 | * @param miPushCommandMessage 72 | * @return 73 | */ 74 | private ReceiverInfo convert2ReceiverInfo(MiPushCommandMessage miPushCommandMessage) { 75 | ReceiverInfo info = new ReceiverInfo(); 76 | info.setContent(miPushCommandMessage.getCommand()); 77 | info.setRawData(miPushCommandMessage); 78 | info.setPushTarget(PushTargetEnum.XIAOMI); 79 | return info; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/target/xiaomi/XiaomiInit.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.target.xiaomi; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.os.Process; 7 | import android.util.Log; 8 | 9 | import com.bearever.push.model.PushTargetEnum; 10 | import com.bearever.push.model.ReceiverInfo; 11 | import com.bearever.push.receiver.PushReceiverHandleManager; 12 | import com.bearever.push.target.BasePushTargetInit; 13 | import com.bearever.push.util.ApplicationUtil; 14 | import com.xiaomi.mipush.sdk.MiPushClient; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * 小米推送的初始化 20 | * Created by luoming on 2018/5/28. 21 | */ 22 | 23 | public class XiaomiInit extends BasePushTargetInit { 24 | private static final String TAG = "XiaomiInit"; 25 | 26 | public XiaomiInit(Application context) { 27 | super(context); 28 | 29 | if (shouldInit()) { 30 | //注册SDK 31 | String appId = ApplicationUtil.getMetaData(context, "XMPUSH_APPID"); 32 | String appKey = ApplicationUtil.getMetaData(context, "XMPUSH_APPKEY"); 33 | 34 | MiPushClient.registerPush(context, appId.replaceAll(" ", ""), 35 | appKey.replaceAll(" ", "")); 36 | 37 | Log.d(TAG, "初始化小米推送"); 38 | } 39 | } 40 | 41 | private boolean shouldInit() { 42 | ActivityManager am = (ActivityManager) mApplication.getSystemService(Context.ACTIVITY_SERVICE); 43 | List processInfos = am.getRunningAppProcesses(); 44 | String mainProcessName = mApplication.getPackageName(); 45 | int myPid = Process.myPid(); 46 | for (ActivityManager.RunningAppProcessInfo info : processInfos) { 47 | if (info.pid == myPid && mainProcessName.equals(info.processName)) { 48 | return true; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | @Override 55 | public void setAlias(Context context, String alias, ReceiverInfo registerInfo) { 56 | MiPushClient.setAlias(context, alias, null); 57 | ReceiverInfo aliasInfo = new ReceiverInfo(); 58 | aliasInfo.setContent(alias); 59 | aliasInfo.setPushTarget(PushTargetEnum.XIAOMI); 60 | PushReceiverHandleManager.getInstance().onAliasSet(context, aliasInfo); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /push/src/main/java/com/bearever/push/util/ApplicationUtil.java: -------------------------------------------------------------------------------- 1 | package com.bearever.push.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.provider.Settings; 9 | 10 | /** 11 | * 系统工具类 12 | * Created by luoming on 2018/5/28. 13 | */ 14 | 15 | public class ApplicationUtil { 16 | /** 17 | * 获取Manifest 里面的meta-data 18 | * 19 | * @param context 20 | * @param key 21 | * @return 22 | */ 23 | public static String getMetaData(Context context, String key) { 24 | ApplicationInfo ai = null; 25 | try { 26 | ai = context.getPackageManager().getApplicationInfo(context.getPackageName(), 27 | PackageManager.GET_META_DATA); 28 | } catch (PackageManager.NameNotFoundException e) { 29 | e.printStackTrace(); 30 | return ""; 31 | } 32 | Bundle bundle = ai.metaData; 33 | String value = bundle.getString(key); 34 | return value; 35 | } 36 | 37 | /** 38 | * 获取设备id 39 | * 40 | * @param context 41 | * @return 42 | */ 43 | public static String getDeviceId(Context context) { 44 | String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 45 | String id = androidID + Build.SERIAL; 46 | return id; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/HMSAgent.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent; 2 | 3 | 4 | import android.app.Activity; 5 | import android.app.Application; 6 | import android.content.Context; 7 | import android.os.Handler; 8 | import android.os.Looper; 9 | import android.widget.Toast; 10 | 11 | import com.bearever.push.PushTargetManager; 12 | import com.huawei.android.hms.agent.common.ActivityMgr; 13 | import com.huawei.android.hms.agent.common.ApiClientMgr; 14 | import com.huawei.android.hms.agent.common.HMSAgentLog; 15 | import com.huawei.android.hms.agent.common.IClientConnectCallback; 16 | import com.huawei.android.hms.agent.common.INoProguard; 17 | import com.huawei.android.hms.agent.common.handler.ConnectHandler; 18 | import com.huawei.android.hms.agent.push.DeleteTokenApi; 19 | import com.huawei.android.hms.agent.push.EnableReceiveNormalMsgApi; 20 | import com.huawei.android.hms.agent.push.EnableReceiveNotifyMsgApi; 21 | import com.huawei.android.hms.agent.push.GetPushStateApi; 22 | import com.huawei.android.hms.agent.push.GetTokenApi; 23 | import com.huawei.android.hms.agent.push.QueryAgreementApi; 24 | import com.huawei.android.hms.agent.push.handler.DeleteTokenHandler; 25 | import com.huawei.android.hms.agent.push.handler.EnableReceiveNormalMsgHandler; 26 | import com.huawei.android.hms.agent.push.handler.EnableReceiveNotifyMsgHandler; 27 | import com.huawei.android.hms.agent.push.handler.GetPushStateHandler; 28 | import com.huawei.android.hms.agent.push.handler.GetTokenHandler; 29 | import com.huawei.android.hms.agent.push.handler.QueryAgreementHandler; 30 | import com.huawei.hms.api.HuaweiApiAvailability; 31 | import com.huawei.hms.api.HuaweiApiClient; 32 | 33 | /** 34 | * HMSAgent 封装入口类。 提供了HMS SDK 功能的封装,使开发者更聚焦业务的处理。 35 | * HMSAgent encapsulates the entry class. Provides a encapsulation of the HMS SDK functionality that enables developers to focus more on business processing. 36 | */ 37 | public final class HMSAgent implements INoProguard { 38 | 39 | /** 40 | * 基础版本 | Base version 41 | */ 42 | private static final String VER_020503001 = "020503001"; 43 | 44 | /** 45 | * 2.6.0 版本1 | 2.6.0 version 1 46 | * 对外:接口不变 | External: interface unchanged 47 | * 对内:HMSSDK connect 接口增加activity参数 | Internal: HMSSDK connect interface to increase activity parameters 48 | * HMSSDK sign 接口增加activity参数 | HMSSDK sign interface to increase activity parameters 49 | * 自身优化: | Self optimization: 50 | * 1、增加了升级时被其他界面覆盖的处理 | Increased handling of other interface coverage issues when upgrading 51 | * 2、game模块savePlayerInfo接口,去掉activity的判断 | Game Module Saveplayerinfo method to remove activity judgments 52 | * 3、解决错误回调成功,增加重试次数3次 | Resolve error callback succeeded, increase retry count 3 times 53 | * 4、提供了多种HMSAgent初始化方法 | Provides a variety of hmsagent initialization methods 54 | * 5、初始化时增加了版本号校验 | Increased version number checksum during initialization 55 | */ 56 | private static final String VER_020600001 = "020600001"; 57 | 58 | /** 59 | * 2.6.0.200 | 2.6.0.200 60 | * 自身优化: | Self optimization: 61 | * 1、增加shell脚本用来抽取代码和编译成jar | Add shell script to extract code and compile into jar 62 | * 2、示例中manifest里面升级配置错误修复 | Example manifest upgrade configuration error Repair 63 | * 3、抽取代码中去掉manifest文件,只留纯代码 | Remove manifest files in the extraction code, leaving only pure code 64 | */ 65 | private static final String VER_020600200 = "020600200"; 66 | 67 | /** 68 | * 2.6.0.302 | 2.6.0.302 69 | * 修改manifest,删除hms版本号配置;增加直接传入请求和私钥的签名方法封装 70 | */ 71 | private static final String VER_020600302 = "020600302"; 72 | 73 | /** 74 | * 当前版本号 | Current version number 75 | */ 76 | public static final String CURVER = VER_020600302; 77 | 78 | 79 | 80 | public static final class AgentResultCode { 81 | 82 | /** 83 | * HMSAgent 成功 | success 84 | */ 85 | public static final int HMSAGENT_SUCCESS = 0; 86 | 87 | /** 88 | * HMSAgent 没有初始化 | Hmsagent not initialized 89 | */ 90 | public static final int HMSAGENT_NO_INIT = -1000; 91 | 92 | /** 93 | * 请求需要activity,但当前没有可用的activity | Request requires activity, but no active activity is currently available 94 | */ 95 | public static final int NO_ACTIVITY_FOR_USE = -1001; 96 | 97 | /** 98 | * 结果为空 | Result is empty 99 | */ 100 | public static final int RESULT_IS_NULL = -1002; 101 | 102 | /** 103 | * 状态为空 | Status is empty 104 | */ 105 | public static final int STATUS_IS_NULL = -1003; 106 | 107 | /** 108 | * 拉起activity异常,需要检查activity有没有在manifest中配置 | Pull up an activity exception and need to check if the activity is configured in manifest 109 | */ 110 | public static final int START_ACTIVITY_ERROR = -1004; 111 | 112 | /** 113 | * onActivityResult 回调结果错误 | Onactivityresult Callback Result Error 114 | */ 115 | public static final int ON_ACTIVITY_RESULT_ERROR = -1005; 116 | 117 | /** 118 | * 重复请求 | Duplicate Request 119 | */ 120 | public static final int REQUEST_REPEATED = -1006; 121 | 122 | /** 123 | * 连接client 超时 | Connect Client Timeout 124 | */ 125 | public static final int APICLIENT_TIMEOUT = -1007; 126 | 127 | /** 128 | * 调用接口异常 | Calling an interface exception 129 | */ 130 | public static final int CALL_EXCEPTION = -1008; 131 | 132 | /** 133 | * 接口参数为空 | Interface parameter is empty 134 | */ 135 | public static final int EMPTY_PARAM = -1009; 136 | } 137 | 138 | private HMSAgent(){} 139 | 140 | private static boolean checkSDKVersion(Context context){ 141 | long sdkMainVerL = HuaweiApiAvailability.HMS_SDK_VERSION_CODE/1000; 142 | long agentMainVerL = Long.parseLong(CURVER)/1000; 143 | if (sdkMainVerL != agentMainVerL) { 144 | String errMsg = "error: HMSAgent major version code ("+agentMainVerL+") does not match HMSSDK major version code ("+sdkMainVerL+")"; 145 | HMSAgentLog.e(errMsg); 146 | Toast.makeText(context, errMsg, Toast.LENGTH_LONG).show(); 147 | return false; 148 | } 149 | return true; 150 | } 151 | 152 | /** 153 | * 初始化方法,传入第一个界面的activity | Initialization method, passing in the first interface activity 154 | * @param activity 当前界面 | Current interface 155 | * @return true:成功 false:失败 | True: Success false: Failed 156 | */ 157 | public static boolean init(Activity activity) { 158 | return init(null, activity); 159 | } 160 | 161 | /** 162 | * 初始化方法,建议在Application onCreate里面调用 | Initialization method, it is recommended to call in creator OnCreate 163 | * @param app 应用程序 | Application 164 | * @return true:成功 false:失败 | True: Success false: Failed 165 | */ 166 | public static boolean init(Application app) { 167 | return init(app, null); 168 | } 169 | 170 | /** 171 | * 初始化方法,建议在Application onCreate里面调用 | Initialization method, it is recommended to call in creator OnCreate 172 | * @param app 应用程序 | Application 173 | * @param activity 当前界面 | Current activity 174 | * @return true:成功 false:失败 | True: Success false: Failed 175 | */ 176 | public static boolean init(Application app, Activity activity) { 177 | 178 | Application appTmp = app; 179 | Activity activityTmp = activity; 180 | 181 | // 两个参数都为null,直接抛异常 | Two parameters are null, throwing exceptions directly 182 | if (appTmp == null && activityTmp == null) { 183 | HMSAgentLog.e("the param of method HMSAgent.init can not be null !!!"); 184 | return false; 185 | } 186 | 187 | // 如果application实例为null,则从activity里面取 | If the creator instance is null, it is taken from the activity 188 | if (appTmp == null) { 189 | appTmp = activityTmp.getApplication(); 190 | } 191 | 192 | // 如果application实例仍然为null,抛异常 | Throws an exception if the creator instance is still null 193 | if (appTmp == null) { 194 | HMSAgentLog.e("the param of method HMSAgent.init app can not be null !!!"); 195 | return false; 196 | } 197 | 198 | // activity 已经失效,则赋值null | Assignment NULL if activity has been invalidated 199 | if (activityTmp != null && activityTmp.isFinishing()) { 200 | activityTmp = null; 201 | } 202 | 203 | // 检查HMSAgent 和 HMSSDK 版本匹配关系 | Check hmsagent and HMSSDK version matching relationships 204 | if (!checkSDKVersion(appTmp)) { 205 | return false; 206 | } 207 | 208 | HMSAgentLog.i("init HMSAgent " + CURVER + " with hmssdkver " + HuaweiApiAvailability.HMS_SDK_VERSION_CODE); 209 | 210 | // 初始化activity管理类 | Initializing Activity Management Classes 211 | ActivityMgr.INST.init(appTmp, activityTmp); 212 | 213 | // 初始化HuaweiApiClient管理类 | Initialize Huaweiapiclient Management class 214 | ApiClientMgr.INST.init(appTmp); 215 | 216 | HMSAgent.connect(new ConnectHandler() { 217 | @Override 218 | public void onConnect(int rst) { 219 | if (rst == HMSAgent.AgentResultCode.HMSAGENT_SUCCESS) { 220 | //连接成功就获取token和设置打开推送等 221 | HMSAgent.Push.getPushState(null); 222 | HMSAgent.Push.getToken(null); 223 | } 224 | } 225 | }); 226 | 227 | return true; 228 | } 229 | 230 | /** 231 | * 释放资源,这里一般不需要调用 | Frees resources, which are generally not required to call 232 | */ 233 | public static void destroy() { 234 | HMSAgentLog.i("destroy HMSAgent"); 235 | ActivityMgr.INST.release(); 236 | ApiClientMgr.INST.release(); 237 | } 238 | 239 | /** 240 | * 连接HMS SDK, 可能拉起界面(包括升级引导等),建议在第一个界面进行连接。 | Connecting to the HMS SDK may pull up the activity (including upgrade guard, etc.), and it is recommended that you connect in the first activity. 241 | * 此方法可以重复调用,没必要为了只调用一次做复杂处理 | This method can be called repeatedly, and there is no need to do complex processing for only one call at a time 242 | * 方法为异步调用,调用结果在主线程回调 | Method is called asynchronously, and the result is invoked in the main thread callback 243 | * @param activity 当前界面的activity, 不能传空 | Activity of the current activity, cannot be empty 244 | * @param callback 连接结果回调 | Connection Result Callback 245 | */ 246 | public static void connect(final ConnectHandler callback) { 247 | HMSAgentLog.i("start connect"); 248 | ApiClientMgr.INST.connect(new IClientConnectCallback() { 249 | @Override 250 | public void onConnect(final int rst, HuaweiApiClient client) { 251 | if (callback != null) { 252 | new Handler(Looper.getMainLooper()).post(new Runnable() { 253 | @Override 254 | public void run() { 255 | callback.onConnect(rst); 256 | } 257 | }); 258 | } 259 | } 260 | }, true); 261 | } 262 | 263 | /** 264 | * 检查本应用的升级 | Check for upgrades to this application 265 | * @param activity 上下文 | context 266 | */ 267 | public static void checkUpdate (final Activity activity) { 268 | HMSAgentLog.i("start checkUpdate"); 269 | ApiClientMgr.INST.connect(new IClientConnectCallback() { 270 | @Override 271 | public void onConnect(int rst, HuaweiApiClient client) { 272 | Activity activityCur = ActivityMgr.INST.getLastActivity(); 273 | 274 | if (activityCur != null && client != null) { 275 | client.checkUpdate(activityCur); 276 | } else if (activity != null && client != null){ 277 | client.checkUpdate(activity); 278 | } else { 279 | // 跟SE确认:activity 为 null , 不处理 | Activity is null and does not need to be processed 280 | HMSAgentLog.e("no activity to checkUpdate"); 281 | } 282 | } 283 | }, true); 284 | } 285 | 286 | 287 | 288 | 289 | 290 | /** 291 | * push接口封装 | Push interface Encapsulation 292 | */ 293 | public static final class Push { 294 | /** 295 | * 获取pushtoken接口 | Get Pushtoken method 296 | * pushtoken通过广播下发,要监听的广播,请参见HMS-SDK开发准备中PushReceiver的注册 | Pushtoken Broadcast issued, to listen to the broadcast, see HMS-SDK Development Preparation Pushreceiver Registration 297 | * @param handler pushtoken接口调用回调(结果会在主线程回调) | getToken method Call callback (result will be callback in main thread) 298 | */ 299 | public static void getToken(GetTokenHandler handler){ 300 | new GetTokenApi().getToken(handler); 301 | } 302 | 303 | /** 304 | * 删除指定的pushtoken | Deletes the specified Pushtoken 305 | * 该接口只在EMUI5.1以及更高版本的华为手机上调用该接口后才不会收到PUSH消息。 | The method will not receive a push message until it is invoked on EMUI5.1 and later Huawei handsets. 306 | * @param token 要删除的token | Token to delete 307 | * @param handler 方法调用结果回调(结果会在主线程回调) | Method call result Callback (result will be callback on main thread) 308 | */ 309 | public static void deleteToken(String token, DeleteTokenHandler handler){ 310 | new DeleteTokenApi().deleteToken(token, handler); 311 | } 312 | 313 | /** 314 | * 获取push状态,push状态的回调通过广播发送。 | Gets the push state, and the push state callback is sent by broadcast. 315 | * 要监听的广播,请参见HMS-SDK开发准备中PushReceiver的注册 | To listen for broadcasts, see Pushreceiver Registration in HMS-SDK development preparation 316 | * @param handler 方法调用结果回调(结果会在主线程回调) | Method call result Callback (result will be callback on main thread) 317 | */ 318 | public static void getPushState(GetPushStateHandler handler){ 319 | new GetPushStateApi().getPushState(handler); 320 | } 321 | 322 | /** 323 | * 打开/关闭通知栏消息 | Turn on/off notification bar messages 324 | * @param enable 打开/关闭 | Turn ON/off 325 | * @param handler 方法调用结果回调(结果会在主线程回调) | Method call result Callback (result will be callback on main thread) 326 | */ 327 | public static void enableReceiveNotifyMsg(boolean enable, EnableReceiveNotifyMsgHandler handler){ 328 | new EnableReceiveNotifyMsgApi().enableReceiveNotifyMsg(enable, handler); 329 | } 330 | 331 | /** 332 | * 打开/关闭透传消息 | Turn on/off the pass message 333 | * @param enable 打开/关闭 | Turn ON/off 334 | * @param handler 方法调用结果回调(结果会在主线程回调) | Method call result Callback (result will be callback on main thread) 335 | */ 336 | public static void enableReceiveNormalMsg(boolean enable, EnableReceiveNormalMsgHandler handler){ 337 | new EnableReceiveNormalMsgApi().enableReceiveNormalMsg(enable, handler); 338 | } 339 | 340 | /** 341 | * 请求push协议展示 | Request Push Protocol Display 342 | * @param handler 方法调用结果回调(结果会在主线程回调)| Method call result Callback (result will be callback on main thread) 343 | */ 344 | public static void queryAgreement(QueryAgreementHandler handler){ 345 | new QueryAgreementApi().queryAgreement(handler); 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/ActivityMgr.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Activity Management Class 12 | * 此类注册了activity的生命周期监听,用来获取最新的activity给后续逻辑处理使用 | This class registers the life cycle monitoring of the activity to obtain the latest activity for subsequent logical processing using 13 | */ 14 | public final class ActivityMgr implements Application.ActivityLifecycleCallbacks { 15 | 16 | /** 17 | * 单实例 | Single Instance 18 | */ 19 | public static final ActivityMgr INST = new ActivityMgr(); 20 | 21 | private static final Object LOCK_LASTACTIVITIES = new Object(); 22 | 23 | /** 24 | * 应用程序 | application 25 | */ 26 | private Application application; 27 | 28 | /** 29 | * 最新的activity列表,如果没有则为空列表 | Latest list of activity, if no, empty list 30 | */ 31 | private List curActivities = new ArrayList(); 32 | 33 | /** 34 | * activity onResume Event Monitoring 35 | */ 36 | private List resumeCallbacks = new ArrayList(); 37 | 38 | /** 39 | * activity onPause Event Monitoring 40 | */ 41 | private List pauseCallbacks = new ArrayList(); 42 | 43 | /** 44 | * activity onDestroyed Event Monitoring 45 | */ 46 | private List destroyedCallbacks = new ArrayList(); 47 | 48 | /** 49 | * 私有构造方法 | Private construction methods 50 | * 防止外面直接创建实例 | Prevent external instances from being created directly 51 | */ 52 | private ActivityMgr(){} 53 | 54 | /** 55 | * 初始化方法 | Initialization method 56 | * @param app 应用程序 | application 57 | */ 58 | public void init(Application app, Activity initActivity) { 59 | HMSAgentLog.d("init"); 60 | 61 | if (application != null) { 62 | application.unregisterActivityLifecycleCallbacks(this); 63 | } 64 | 65 | application = app; 66 | setCurActivity(initActivity); 67 | app.registerActivityLifecycleCallbacks(this); 68 | } 69 | 70 | /** 71 | * 释放资源,一般不需要调用 | Frees resources, and generally does not need to call 72 | */ 73 | public void release() { 74 | HMSAgentLog.d("release"); 75 | if (application != null) { 76 | application.unregisterActivityLifecycleCallbacks(this); 77 | } 78 | 79 | clearCurActivities(); 80 | clearActivitResumeCallbacks(); 81 | clearActivitPauseCallbacks(); 82 | application = null; 83 | } 84 | 85 | /** 86 | * 注册activity onResume事件回调 | Registering an Activity Onresume event Callback 87 | * @param callback activity onResume事件回调 | Activity Onresume Event Callback 88 | */ 89 | public void registerActivitResumeEvent(IActivityResumeCallback callback) { 90 | HMSAgentLog.d("registerOnResume:" + StrUtils.objDesc(callback)); 91 | resumeCallbacks.add(callback); 92 | } 93 | 94 | /** 95 | * 反注册activity onResume事件回调 | unregistration Activity Onresume Event Callback 96 | * @param callback 已经注册的 activity onResume事件回调 | Registered Activity Onresume Event callback 97 | */ 98 | public void unRegisterActivitResumeEvent(IActivityResumeCallback callback) { 99 | HMSAgentLog.d("unRegisterOnResume:" + StrUtils.objDesc(callback)); 100 | resumeCallbacks.remove(callback); 101 | } 102 | 103 | /** 104 | * 注册activity onPause 事件回调 | Registering an Activity OnPause event Callback 105 | * @param callback activity onPause 事件回调 | Activity OnPause Event Callback 106 | */ 107 | public void registerActivitPauseEvent(IActivityPauseCallback callback) { 108 | HMSAgentLog.d("registerOnPause:" + StrUtils.objDesc(callback)); 109 | pauseCallbacks.add(callback); 110 | } 111 | 112 | /** 113 | * 反注册activity onPause事件回调 | unregistration activity OnPause Event Callback 114 | * @param callback 已经注册的 activity onPause事件回调 | Registered Activity OnPause Event callback 115 | */ 116 | public void unRegisterActivitPauseEvent(IActivityPauseCallback callback) { 117 | HMSAgentLog.d("unRegisterOnPause:" + StrUtils.objDesc(callback)); 118 | pauseCallbacks.remove(callback); 119 | } 120 | 121 | /** 122 | * 注册activity onDestroyed 事件回调 | Registering an Activity ondestroyed event Callback 123 | * @param callback activity onDestroyed 事件回调 | Activity Ondestroyed Event Callback 124 | */ 125 | public void registerActivitDestroyedEvent(IActivityDestroyedCallback callback) { 126 | HMSAgentLog.d("registerOnDestroyed:" + StrUtils.objDesc(callback)); 127 | destroyedCallbacks.add(callback); 128 | } 129 | 130 | /** 131 | * 反注册activity onDestroyed 事件回调 | unregistration Activity ondestroyed Event Callback 132 | * @param callback 已经注册的 activity onDestroyed事件回调 | Registered Activity ondestroyed Event callback 133 | */ 134 | public void unRegisterActivitDestroyedEvent(IActivityDestroyedCallback callback) { 135 | HMSAgentLog.d("unRegisterOnDestroyed:" + StrUtils.objDesc(callback)); 136 | destroyedCallbacks.remove(callback); 137 | } 138 | 139 | /** 140 | * 清空 activity onResume事件回调 | Clear Activity Onresume Event callback 141 | */ 142 | public void clearActivitResumeCallbacks() { 143 | HMSAgentLog.d("clearOnResumeCallback"); 144 | resumeCallbacks.clear(); 145 | } 146 | 147 | /** 148 | * 清空 activity onPause 事件回调 | Clear Activity OnPause Event callback 149 | */ 150 | public void clearActivitPauseCallbacks() { 151 | HMSAgentLog.d("clearOnPauseCallback"); 152 | pauseCallbacks.clear(); 153 | } 154 | 155 | /** 156 | * 获取最新的activity | Get the latest activity 157 | * @return 最新的activity | Latest activity 158 | */ 159 | public Activity getLastActivity() { 160 | return getLastActivityInner(); 161 | } 162 | 163 | /** 164 | * activity onCreate 监听回调 | Activity OnCreate Listener Callback 165 | * @param activity 发生onCreate事件的activity | Activity that occurs OnCreate events 166 | * @param savedInstanceState 缓存状态数据 | Cached state data 167 | */ 168 | @Override 169 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 170 | HMSAgentLog.d("onCreated:" + StrUtils.objDesc(activity)); 171 | setCurActivity(activity); 172 | } 173 | 174 | /** 175 | * activity onStart 监听回调 | Activity OnStart Listener Callback 176 | * @param activity 发生onStart事件的activity | Activity that occurs OnStart events 177 | */ 178 | @Override 179 | public void onActivityStarted(Activity activity) { 180 | HMSAgentLog.d("onStarted:" + StrUtils.objDesc(activity)); 181 | setCurActivity(activity); 182 | } 183 | 184 | /** 185 | * activity onResume 监听回调 | Activity Onresume Listener Callback 186 | * @param activity 发生onResume事件的activity | Activity that occurs Onresume events 187 | */ 188 | @Override 189 | public void onActivityResumed(Activity activity) { 190 | HMSAgentLog.d("onResumed:" + StrUtils.objDesc(activity)); 191 | setCurActivity(activity); 192 | 193 | List tmdCallbacks = new ArrayList(resumeCallbacks); 194 | for (IActivityResumeCallback callback : tmdCallbacks) { 195 | callback.onActivityResume(activity); 196 | } 197 | } 198 | 199 | /** 200 | * activity onPause 监听回调 | Activity OnPause Listener Callback 201 | * @param activity 发生onPause事件的activity | Activity that occurs OnPause events 202 | */ 203 | @Override 204 | public void onActivityPaused(Activity activity) { 205 | HMSAgentLog.d("onPaused:" + StrUtils.objDesc(activity)); 206 | List tmdCallbacks = new ArrayList(pauseCallbacks); 207 | for (IActivityPauseCallback callback : tmdCallbacks) { 208 | callback.onActivityPause(activity); 209 | } 210 | } 211 | 212 | /** 213 | * activity onStop 监听回调 | Activity OnStop Listener Callback 214 | * @param activity 发生onStop事件的activity | Activity that occurs OnStop events 215 | */ 216 | @Override 217 | public void onActivityStopped(Activity activity) { 218 | HMSAgentLog.d("onStopped:" + StrUtils.objDesc(activity)); 219 | } 220 | 221 | /** 222 | * activity onSaveInstanceState 监听回调 | Activity Onsaveinstancestate Listener Callback 223 | * @param activity 发生 onSaveInstanceState 事件的activity | Activity that occurs onsaveinstancestate events 224 | */ 225 | @Override 226 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 227 | } 228 | 229 | /** 230 | * activity onDestroyed 监听回调 | Activity Ondestroyed Listener Callback 231 | * @param activity 发生 onDestroyed 事件的activity | Activity that occurs ondestroyed events 232 | */ 233 | @Override 234 | public void onActivityDestroyed(Activity activity) { 235 | HMSAgentLog.d("onDestroyed:" + StrUtils.objDesc(activity)); 236 | removeActivity(activity); 237 | 238 | // activity onDestroyed 事件回调 | Activity Ondestroyed Event Callback 239 | List tmdCallbacks = new ArrayList(destroyedCallbacks); 240 | for (IActivityDestroyedCallback callback : tmdCallbacks) { 241 | callback.onActivityDestroyed(activity, getLastActivityInner()); 242 | } 243 | } 244 | 245 | /** 246 | * 移除当前activity | Remove Current Activity 247 | * @param curActivity 要移除的activity | Activity to remove 248 | */ 249 | private void removeActivity(Activity curActivity) { 250 | synchronized (LOCK_LASTACTIVITIES) { 251 | curActivities.remove(curActivity); 252 | } 253 | } 254 | 255 | /** 256 | * 设置最新的activity | Set up the latest activity 257 | * @param curActivity 最新的activity | Latest activity 258 | */ 259 | private void setCurActivity(Activity curActivity) { 260 | synchronized (LOCK_LASTACTIVITIES) { 261 | int idxCurActivity = curActivities.indexOf(curActivity); 262 | if (idxCurActivity == -1) { 263 | curActivities.add(curActivity); 264 | } else if (idxCurActivity < curActivities.size()-1){ 265 | curActivities.remove(curActivity); 266 | curActivities.add(curActivity); 267 | } 268 | } 269 | } 270 | 271 | /** 272 | * 获取最新的activity,如果没有则返回null | Gets the latest activity and returns null if not 273 | * @return 最新的activity | Latest activity 274 | */ 275 | private Activity getLastActivityInner(){ 276 | synchronized (LOCK_LASTACTIVITIES) { 277 | if (curActivities.size() > 0) { 278 | return curActivities.get(curActivities.size()-1); 279 | } else { 280 | return null; 281 | } 282 | } 283 | } 284 | 285 | /** 286 | * 清理activities | Clean activities 287 | */ 288 | private void clearCurActivities(){ 289 | synchronized (LOCK_LASTACTIVITIES) { 290 | curActivities.clear(); 291 | } 292 | } 293 | } -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/ApiClientMgr.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Handler; 8 | import android.os.Message; 9 | 10 | import com.huawei.android.hms.agent.HMSAgent; 11 | import com.huawei.hms.activity.BridgeActivity; 12 | import com.huawei.hms.api.ConnectionResult; 13 | import com.huawei.hms.api.HuaweiApiAvailability; 14 | import com.huawei.hms.api.HuaweiApiClient; 15 | import com.huawei.hms.support.api.push.HuaweiPush; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | 21 | /** 22 | * Huawei Api Client 管理类 | Huawei API Client Management class 23 | * 负责HuaweiApiClient的连接,异常处理等 | Responsible for huaweiapiclient connection, exception handling, etc. 24 | */ 25 | public final class ApiClientMgr implements HuaweiApiClient.ConnectionCallbacks, HuaweiApiClient.OnConnectionFailedListener, IActivityResumeCallback, IActivityPauseCallback, IActivityDestroyedCallback { 26 | 27 | /** 28 | * 单实例 29 | */ 30 | public static final ApiClientMgr INST = new ApiClientMgr(); 31 | 32 | /** 33 | * 应用市场包名 34 | */ 35 | private static final String PACKAGE_NAME_HIAPP = "com.huawei.appmarket"; 36 | 37 | /** 38 | * 回调锁,避免连接回调紊乱 39 | */ 40 | private static final Object CALLBACK_LOCK = new Object(); 41 | 42 | /** 43 | * 静态注册回调锁,避免注册和回调紊乱 44 | */ 45 | private static final Object STATIC_CALLBACK_LOCK = new Object(); 46 | 47 | /** 48 | * client操作锁,避免连接使用紊乱 49 | */ 50 | private static final Object APICLIENT_LOCK = new Object(); 51 | 52 | /** 53 | * api client 连接超时 54 | */ 55 | private static final int APICLIENT_CONNECT_TIMEOUT = 30000; 56 | 57 | /** 58 | * 解决升级错误时activity onResume 稳定在3秒时间判断BridgeActivity上面有没有其他activity 59 | */ 60 | private static final int UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT = 3000; 61 | 62 | /** 63 | * api client 解决错误拉起界面超时 64 | */ 65 | private static final int APICLIENT_STARTACTIVITY_TIMEOUT = 3000; 66 | 67 | /** 68 | * client 连接超时消息 69 | */ 70 | private static final int APICLIENT_TIMEOUT_HANDLE_MSG = 3; 71 | 72 | /** 73 | * client 拉起activity超时消息 74 | */ 75 | private static final int APICLIENT_STARTACTIVITY_TIMEOUT_HANDLE_MSG = 4; 76 | 77 | /** 78 | * 解决升级错误时activity onResume 稳定在3秒时间判断BridgeActivity上面有没有其他activity 79 | */ 80 | private static final int UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT_HANDLE_MSG = 5; 81 | 82 | /** 83 | * 最大尝试连接次数 84 | */ 85 | private static final int MAX_RESOLVE_TIMES = 3; 86 | 87 | /** 88 | * 上下文,用来处理连接失败 89 | */ 90 | private Context context; 91 | 92 | /** 93 | * 当前应用包名 94 | */ 95 | private String curAppPackageName; 96 | 97 | /** 98 | * HuaweiApiClient 实例 99 | */ 100 | private HuaweiApiClient apiClient; 101 | 102 | /** 103 | * 是否允许解决connect错误(解决connect错误需要拉起activity) 104 | */ 105 | private boolean allowResolveConnectError = false; 106 | 107 | /** 108 | * 是否正在解决连接错误 109 | */ 110 | private boolean isResolving; 111 | 112 | /** 113 | * HMSSDK 解决错误的activity 114 | */ 115 | private BridgeActivity resolveActivity; 116 | 117 | /** 118 | * 是否存在其他activity覆盖在升级activity之上 119 | */ 120 | private boolean hasOverActivity = false; 121 | 122 | /** 123 | * 当前剩余尝试次数 124 | */ 125 | private int curLeftResolveTimes = MAX_RESOLVE_TIMES; 126 | 127 | /** 128 | * 连接回调 129 | */ 130 | private List connCallbacks = new ArrayList(); 131 | 132 | /** 133 | * 注册的静态回调 134 | */ 135 | private List staticCallbacks = new ArrayList(); 136 | 137 | /** 138 | * 超时handler用来处理client connect 超时 139 | */ 140 | private Handler timeoutHandler = new Handler(new Handler.Callback() { 141 | @Override 142 | public boolean handleMessage(Message msg) { 143 | 144 | boolean hasConnCallbacks; 145 | synchronized (CALLBACK_LOCK) { 146 | hasConnCallbacks = !connCallbacks.isEmpty(); 147 | } 148 | 149 | if (msg != null && msg.what == APICLIENT_TIMEOUT_HANDLE_MSG && hasConnCallbacks) { 150 | HMSAgentLog.d("connect time out"); 151 | resetApiClient(); 152 | onConnectEnd(HMSAgent.AgentResultCode.APICLIENT_TIMEOUT); 153 | return true; 154 | } else if (msg != null && msg.what == APICLIENT_STARTACTIVITY_TIMEOUT_HANDLE_MSG && hasConnCallbacks) { 155 | HMSAgentLog.d("start activity time out"); 156 | onConnectEnd(HMSAgent.AgentResultCode.APICLIENT_TIMEOUT); 157 | return true; 158 | } else if (msg != null && msg.what == UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT_HANDLE_MSG && hasConnCallbacks) { 159 | HMSAgentLog.d("Discarded update dispose:hasOverActivity=" +hasOverActivity + " resolveActivity=" + StrUtils.objDesc(resolveActivity)); 160 | if (hasOverActivity && resolveActivity != null && !resolveActivity.isFinishing()) { 161 | onResolveErrorRst(ConnectionResult.CANCELED); 162 | } 163 | return true; 164 | } 165 | return false; 166 | } 167 | }); 168 | 169 | /** 170 | * 私有构造方法 171 | */ 172 | private ApiClientMgr () { 173 | } 174 | 175 | /** 176 | * 初始化 177 | * @param app 应用程序 178 | */ 179 | public void init(Application app) { 180 | 181 | HMSAgentLog.d("init"); 182 | 183 | // 保存应用程序context 184 | context = app.getApplicationContext(); 185 | 186 | // 取得应用程序包名 187 | curAppPackageName = app.getPackageName(); 188 | 189 | // 注册activity onResume回调 190 | ActivityMgr.INST.unRegisterActivitResumeEvent(this); 191 | ActivityMgr.INST.registerActivitResumeEvent(this); 192 | 193 | // 注册activity onPause回调 194 | ActivityMgr.INST.unRegisterActivitPauseEvent(this); 195 | ActivityMgr.INST.registerActivitPauseEvent(this); 196 | 197 | // 注册activity onDestroyed 回调 198 | ActivityMgr.INST.unRegisterActivitDestroyedEvent(this); 199 | ActivityMgr.INST.registerActivitDestroyedEvent(this); 200 | } 201 | 202 | /** 203 | * 断开apiclient,一般不需要调用 204 | */ 205 | public void release() { 206 | HMSAgentLog.d("release"); 207 | 208 | isResolving = false; 209 | resolveActivity = null; 210 | hasOverActivity = false; 211 | 212 | HuaweiApiClient client = getApiClient(); 213 | if (client != null) { 214 | client.disconnect(); 215 | synchronized (APICLIENT_LOCK) { 216 | apiClient = null; 217 | } 218 | } 219 | 220 | synchronized (STATIC_CALLBACK_LOCK) { 221 | staticCallbacks.clear(); 222 | } 223 | 224 | synchronized (CALLBACK_LOCK) { 225 | connCallbacks.clear(); 226 | } 227 | } 228 | 229 | /** 230 | * 获取当前的 HuaweiApiClient 231 | * @return HuaweiApiClient 实例 232 | */ 233 | public HuaweiApiClient getApiClient() { 234 | synchronized (APICLIENT_LOCK) { 235 | return apiClient; 236 | } 237 | } 238 | 239 | /** 240 | * 判断client是否已经连接 241 | * @param client 要检测的client 242 | * @return 是否已经连接 243 | */ 244 | public boolean isConnect(HuaweiApiClient client) { 245 | return client != null && client.isConnected(); 246 | } 247 | 248 | /** 249 | * 注册apiclient连接事件 250 | * @param staticCallback 连接回调 251 | */ 252 | public void registerClientConnect(IClientConnectCallback staticCallback){ 253 | synchronized (STATIC_CALLBACK_LOCK) { 254 | staticCallbacks.add(staticCallback); 255 | } 256 | } 257 | 258 | /** 259 | * 反注册apiclient连接事件 260 | * @param staticCallback 连接回调 261 | */ 262 | public void removeClientConnectCallback(IClientConnectCallback staticCallback) { 263 | synchronized (STATIC_CALLBACK_LOCK) { 264 | staticCallbacks.remove(staticCallback); 265 | } 266 | } 267 | 268 | /** 269 | * 重新创建apiclient 270 | * 2种情况需要重新创建:1、首次 2、client的状态已经紊乱 271 | * @return 新创建的client 272 | */ 273 | private HuaweiApiClient resetApiClient(){ 274 | synchronized (APICLIENT_LOCK) { 275 | if (apiClient != null) { 276 | // 对于老的apiClient,1分钟后才丢弃,防止外面正在使用过程中这边disConnect了 277 | disConnectClientDelay(apiClient, 60000); 278 | } 279 | 280 | HMSAgentLog.d("reset client"); 281 | 282 | // 这种重置client,极端情况可能会出现2个client都回调结果的情况。此时可能出现rstCode=0,但是client无效。 283 | // 因为业务调用封装中都进行了一次重试。所以不会有问题 284 | apiClient = new HuaweiApiClient.Builder(context) 285 | .addApi(HuaweiPush.PUSH_API) 286 | .addConnectionCallbacks(INST) 287 | .addOnConnectionFailedListener(INST) 288 | .build(); 289 | return apiClient; 290 | } 291 | } 292 | 293 | /** 294 | * 连接 HuaweiApiClient, 295 | * @param callback 连接结果回调,一定不能为null,在子线程进行回调 296 | * @param allowResolve 是否允许解决错误,解决错误时可能会拉起界面 297 | */ 298 | public void connect(IClientConnectCallback callback, boolean allowResolve) { 299 | 300 | if (context == null) { 301 | aSysnCallback(HMSAgent.AgentResultCode.HMSAGENT_NO_INIT, callback); 302 | return; 303 | } 304 | 305 | HuaweiApiClient client = getApiClient(); 306 | // client 有效,则直接回调 307 | if (client != null && client.isConnected()) { 308 | HMSAgentLog.d("client is valid"); 309 | aSysnCallback(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS, callback); 310 | return; 311 | } else { 312 | // client无效,将callback加入队列,并启动连接 313 | synchronized (CALLBACK_LOCK) { 314 | HMSAgentLog.d("client is invalid:size=" + connCallbacks.size()); 315 | allowResolveConnectError = allowResolveConnectError || allowResolve; 316 | if (connCallbacks.isEmpty()) { 317 | connCallbacks.add(callback); 318 | 319 | // 连接尝试最大次数 320 | curLeftResolveTimes = MAX_RESOLVE_TIMES; 321 | 322 | startConnect(); 323 | } else { 324 | connCallbacks.add(callback); 325 | } 326 | } 327 | } 328 | } 329 | 330 | /** 331 | * 线程中进行Huawei Api Client 的连接 332 | */ 333 | private void startConnect() { 334 | 335 | // 触发一次连接将重试次数减1 336 | curLeftResolveTimes--; 337 | 338 | HMSAgentLog.d("start thread to connect"); 339 | ThreadUtil.INST.excute(new Runnable() { 340 | @Override 341 | public void run() { 342 | HuaweiApiClient client = getApiClient(); 343 | if (client == null) { 344 | HMSAgentLog.d("create client"); 345 | client = resetApiClient(); 346 | } 347 | 348 | HMSAgentLog.d("connect"); 349 | Activity curActivity = ActivityMgr.INST.getLastActivity(); 350 | 351 | // 考虑到有cp后台需要调用接口,HMSSDK去掉了activity不能为空的判断。这里只是取当前activity,可能为空 352 | timeoutHandler.sendEmptyMessageDelayed(APICLIENT_TIMEOUT_HANDLE_MSG, APICLIENT_CONNECT_TIMEOUT); 353 | client.connect(curActivity); 354 | } 355 | }); 356 | } 357 | 358 | /** 359 | * Huawei Api Client 连接结束方法 360 | * @param rstCode client 连接结果码 361 | */ 362 | private void onConnectEnd(final int rstCode) { 363 | HMSAgentLog.d("connect end:" + rstCode); 364 | 365 | synchronized (CALLBACK_LOCK) { 366 | // 回调各个回调接口连接结束 367 | for (IClientConnectCallback callback : connCallbacks) { 368 | aSysnCallback(rstCode, callback); 369 | } 370 | connCallbacks.clear(); 371 | 372 | // 恢复默认不显示 373 | allowResolveConnectError = false; 374 | } 375 | 376 | synchronized (STATIC_CALLBACK_LOCK) { 377 | // 回调各个回调接口连接结束 378 | for (IClientConnectCallback callback : staticCallbacks) { 379 | aSysnCallback(rstCode, callback); 380 | } 381 | staticCallbacks.clear(); 382 | } 383 | } 384 | 385 | /** 386 | * 起线程回调各个接口,避免其中一个回调者耗时长影响其他调用者 387 | * @param rstCode 结果码 388 | * @param callback 回调 389 | */ 390 | private void aSysnCallback(final int rstCode, final IClientConnectCallback callback) { 391 | ThreadUtil.INST.excute(new Runnable() { 392 | @Override 393 | public void run() { 394 | HuaweiApiClient client = getApiClient(); 395 | HMSAgentLog.d("callback connect: rst=" + rstCode + " apiClient=" + client); 396 | callback.onConnect(rstCode, client); 397 | } 398 | }); 399 | } 400 | 401 | /** 402 | * Activity onResume回调 403 | * 404 | * @param activity 发生 onResume 事件的activity 405 | */ 406 | @Override 407 | public void onActivityResume(Activity activity) { 408 | // 通知hmssdk activity onResume了 409 | if (apiClient != null) { 410 | HMSAgentLog.d("tell hmssdk: onResume"); 411 | apiClient.onResume(activity); 412 | } 413 | 414 | // 如果正在解决错误,则处理被覆盖的场景 415 | HMSAgentLog.d("is resolving:" + isResolving); 416 | if (isResolving && !PACKAGE_NAME_HIAPP.equals(curAppPackageName)) { 417 | if (activity instanceof BridgeActivity) { 418 | resolveActivity = (BridgeActivity)activity; 419 | hasOverActivity = false; 420 | HMSAgentLog.d("received bridgeActivity:" + StrUtils.objDesc(resolveActivity)); 421 | } else if (resolveActivity != null && !resolveActivity.isFinishing()){ 422 | hasOverActivity = true; 423 | HMSAgentLog.d("received other Activity:" + StrUtils.objDesc(resolveActivity)); 424 | } 425 | timeoutHandler.removeMessages(UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT_HANDLE_MSG); 426 | timeoutHandler.sendEmptyMessageDelayed(UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT_HANDLE_MSG, UPDATE_OVER_ACTIVITY_CHECK_TIMEOUT); 427 | } 428 | } 429 | 430 | /** 431 | * Activity onPause回调 432 | * 433 | * @param activity 发生 onPause 事件的activity 434 | */ 435 | @Override 436 | public void onActivityPause(Activity activity) { 437 | // 通知hmssdk,activity onPause了 438 | if (apiClient != null) { 439 | apiClient.onPause(activity); 440 | } 441 | } 442 | 443 | /** 444 | * Activity onPause回调 445 | * 446 | * @param activityDestroyed 发生 onDestroyed 事件的activity 447 | * @param activityNxt 下个要显示的activity 448 | */ 449 | @Override 450 | public void onActivityDestroyed(Activity activityDestroyed, Activity activityNxt) { 451 | if (activityNxt == null) { 452 | // 所有activity销毁后,重置client,否则公告的标志位还在,下次弹不出来 453 | resetApiClient(); 454 | } 455 | } 456 | 457 | /** 458 | * connect fail 解决结果回调, 由 HMSAgentActivity 在 onActivityResult 中调用 459 | * @param result 解决结果 460 | */ 461 | void onResolveErrorRst(int result) { 462 | HMSAgentLog.d("result="+result); 463 | isResolving = false; 464 | resolveActivity = null; 465 | hasOverActivity = false; 466 | 467 | if(result == ConnectionResult.SUCCESS) { 468 | HuaweiApiClient client = getApiClient(); 469 | if (!client.isConnecting() && !client.isConnected() && curLeftResolveTimes > 0) { 470 | startConnect(); 471 | return; 472 | } 473 | } 474 | 475 | onConnectEnd(result); 476 | } 477 | 478 | /** 479 | * HMSAgentActivity 拉起拉了(走了onCreate) 480 | */ 481 | void onActivityLunched(){ 482 | HMSAgentLog.d("resolve onActivityLunched"); 483 | // 拉起界面回调,移除拉起界面超时 484 | timeoutHandler.removeMessages(APICLIENT_STARTACTIVITY_TIMEOUT_HANDLE_MSG); 485 | isResolving = true; 486 | } 487 | 488 | /** 489 | * Huawe Api Client 连接成功回到 490 | */ 491 | @Override 492 | public void onConnected() { 493 | HMSAgentLog.d("connect success"); 494 | timeoutHandler.removeMessages(APICLIENT_TIMEOUT_HANDLE_MSG); 495 | onConnectEnd(ConnectionResult.SUCCESS); 496 | } 497 | 498 | /** 499 | * 当client变成断开状态时会被调用。这有可能发生在远程服务出现问题时(例如:出现crash或资源问题导致服务被系统杀掉)。 500 | * 当被调用时,所有的请求都会被取消,任何listeners都不会被执行。需要 CP 开发代码尝试恢复连接(connect)。 501 | * 应用程序应该禁用需要服务的相关UI组件,等待{@link #onConnected()} 回调后重新启用他们。
502 | * 503 | * @param cause 断开的原因. 常量定义: CAUSE_*. 504 | */ 505 | @Override 506 | public void onConnectionSuspended(int cause) { 507 | HMSAgentLog.d("connect suspended"); 508 | connect(new EmptyConnectCallback("onConnectionSuspended try end:"), true); 509 | } 510 | 511 | /** 512 | * 建立client到service的连接失败时调用 513 | * 514 | * @param result 连接结果,用于解决错误和知道什么类型的错误 515 | */ 516 | @Override 517 | public void onConnectionFailed(ConnectionResult result) { 518 | timeoutHandler.removeMessages(APICLIENT_TIMEOUT_HANDLE_MSG); 519 | 520 | if (result == null) { 521 | HMSAgentLog.e("result is null"); 522 | onConnectEnd(HMSAgent.AgentResultCode.RESULT_IS_NULL); 523 | return; 524 | } 525 | 526 | int errCode = result.getErrorCode(); 527 | HMSAgentLog.d("errCode=" + errCode + " allowResolve=" + allowResolveConnectError); 528 | 529 | if(HuaweiApiAvailability.getInstance().isUserResolvableError(errCode) && allowResolveConnectError) { 530 | Activity activity = ActivityMgr.INST.getLastActivity(); 531 | if (activity != null) { 532 | try { 533 | timeoutHandler.sendEmptyMessageDelayed(APICLIENT_STARTACTIVITY_TIMEOUT_HANDLE_MSG, APICLIENT_STARTACTIVITY_TIMEOUT); 534 | Intent intent = new Intent(activity, HMSAgentActivity.class); 535 | intent.putExtra(HMSAgentActivity.CONN_ERR_CODE_TAG, errCode); 536 | activity.startActivity(intent); 537 | return; 538 | } catch (Exception e) { 539 | HMSAgentLog.e("start HMSAgentActivity exception:" + e.getMessage()); 540 | timeoutHandler.removeMessages(APICLIENT_STARTACTIVITY_TIMEOUT_HANDLE_MSG); 541 | onConnectEnd(HMSAgent.AgentResultCode.START_ACTIVITY_ERROR); 542 | return; 543 | } 544 | } else { 545 | // 当前没有界面处理不了错误 546 | HMSAgentLog.d("no activity"); 547 | onConnectEnd(HMSAgent.AgentResultCode.NO_ACTIVITY_FOR_USE); 548 | return; 549 | } 550 | } else { 551 | //其他错误码直接透传 552 | } 553 | 554 | onConnectEnd(errCode); 555 | } 556 | 557 | private static void disConnectClientDelay(final HuaweiApiClient clientTmp, int delay) { 558 | new Handler().postDelayed(new Runnable() { 559 | @Override 560 | public void run() { 561 | clientTmp.disconnect(); 562 | } 563 | }, delay); 564 | } 565 | } 566 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/BaseAgentActivity.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.Window; 6 | 7 | /** 8 | * 基础activity,用来处理公共的透明参数 9 | */ 10 | public class BaseAgentActivity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | requestActivityTransparent(); 16 | } 17 | 18 | /** 19 | * 启用透明的跳板Activity 20 | */ 21 | private void requestActivityTransparent() { 22 | requestWindowFeature(Window.FEATURE_NO_TITLE); 23 | Window window = getWindow(); 24 | if (window != null) { 25 | window.addFlags(0x04000000); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/BaseApiAgent.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * API 实现类基类,用于处理公共操作 5 | * 目前实现的是client的连接及回调 6 | */ 7 | public abstract class BaseApiAgent implements IClientConnectCallback { 8 | protected void connect() { 9 | HMSAgentLog.d("connect"); 10 | ApiClientMgr.INST.connect(this, true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/CallbackCodeRunnable.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 回调线程 5 | */ 6 | public class CallbackCodeRunnable implements Runnable { 7 | 8 | private ICallbackCode handlerInner; 9 | private int rtnCodeInner; 10 | 11 | public CallbackCodeRunnable(ICallbackCode handler, int rtnCode) { 12 | handlerInner = handler; 13 | rtnCodeInner = rtnCode; 14 | } 15 | 16 | @Override 17 | public void run() { 18 | if (handlerInner != null) { 19 | handlerInner.onResult(rtnCodeInner); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/CallbackResultRunnable.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 回调线程 5 | */ 6 | public class CallbackResultRunnable implements Runnable { 7 | 8 | private ICallbackResult handlerInner; 9 | private int rtnCodeInner; 10 | private R resultInner; 11 | 12 | public CallbackResultRunnable(ICallbackResult handler, int rtnCode, R payInfo) { 13 | handlerInner = handler; 14 | rtnCodeInner = rtnCode; 15 | resultInner = payInfo; 16 | } 17 | 18 | @Override 19 | public void run() { 20 | if (handlerInner != null) { 21 | handlerInner.onResult(rtnCodeInner, resultInner); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/EmptyConnectCallback.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import com.huawei.hms.api.HuaweiApiClient; 4 | 5 | /** 6 | * 连接client空回调 7 | */ 8 | public class EmptyConnectCallback implements IClientConnectCallback { 9 | 10 | private String msgPre; 11 | 12 | public EmptyConnectCallback(String msgPre){ 13 | this.msgPre = msgPre; 14 | } 15 | 16 | /** 17 | * HuaweiApiClient 连接结果回调 18 | * 19 | * @param rst 结果码 20 | * @param client HuaweiApiClient 实例 21 | */ 22 | @Override 23 | public void onConnect(int rst, HuaweiApiClient client) { 24 | HMSAgentLog.d(msgPre + rst); 25 | } 26 | } -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/HMSAgentActivity.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.huawei.android.hms.agent.HMSAgent; 8 | import com.huawei.hms.api.HuaweiApiAvailability; 9 | 10 | /** 11 | * 代理Activity,用于弹出解决问题的引导 12 | */ 13 | public class HMSAgentActivity extends BaseAgentActivity { 14 | 15 | /** 16 | * 参数标签,用于取得要解决的错误码 17 | */ 18 | public static final String CONN_ERR_CODE_TAG = "HMSConnectionErrorCode"; 19 | 20 | /** 21 | * 解决错误后结果的标签,用来取得解决的结果 22 | */ 23 | public static final String EXTRA_RESULT = "intent.extra.RESULT"; 24 | 25 | /** 26 | * 解决错误的requestCode 27 | */ 28 | private static final int REQUEST_HMS_RESOLVE_ERROR = 1000; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | ApiClientMgr.INST.onActivityLunched(); 34 | 35 | Intent intent = getIntent(); 36 | if (intent != null) { 37 | int rstCode = intent.getIntExtra(CONN_ERR_CODE_TAG, 0); 38 | HMSAgentLog.d("dispose code:" + rstCode); 39 | HuaweiApiAvailability.getInstance().resolveError(this, rstCode, REQUEST_HMS_RESOLVE_ERROR); 40 | } else { 41 | HMSAgentLog.e("intent is null"); 42 | finish(); 43 | } 44 | } 45 | 46 | @Override 47 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 48 | super.onActivityResult(requestCode, resultCode, data); 49 | 50 | if(requestCode == REQUEST_HMS_RESOLVE_ERROR) { 51 | if(resultCode == Activity.RESULT_OK) { 52 | 53 | int result = data.getIntExtra(EXTRA_RESULT, -1); 54 | HMSAgentLog.d("dispose result:" + result); 55 | ApiClientMgr.INST.onResolveErrorRst(result); 56 | } else { 57 | HMSAgentLog.e("dispose error:" + resultCode); 58 | ApiClientMgr.INST.onResolveErrorRst(HMSAgent.AgentResultCode.ON_ACTIVITY_RESULT_ERROR); 59 | } 60 | finish(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/HMSAgentLog.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * 日志打印类,对打印日志进行封装,方便根据日志定位问题 7 | */ 8 | public final class HMSAgentLog { 9 | 10 | /** 11 | * 日志回调,将要打印的日志回调给开发者,由开发者将日志输出 12 | */ 13 | public interface IHMSAgentLogCallback { 14 | void logD(String tag, String log); 15 | void logV(String tag, String log); 16 | void logI(String tag, String log); 17 | void logW(String tag, String log); 18 | void logE(String tag, String log); 19 | } 20 | 21 | private static final int START_STACK_INDEX = 4; 22 | private static final int PRINT_STACK_COUTN = 2; 23 | 24 | private static IHMSAgentLogCallback logCallback = null; 25 | 26 | public static void setHMSAgentLogCallback(IHMSAgentLogCallback callback){ 27 | logCallback = callback; 28 | } 29 | 30 | public static void d(String log) { 31 | StringBuilder sb = new StringBuilder(); 32 | appendStack(sb); 33 | sb.append(log); 34 | 35 | if (logCallback != null) { 36 | logCallback.logD("HMSAgent", sb.toString()); 37 | } else { 38 | Log.d("HMSAgent", sb.toString()); 39 | } 40 | } 41 | 42 | public static void v(String log) { 43 | StringBuilder sb = new StringBuilder(); 44 | appendStack(sb); 45 | sb.append(log); 46 | if (logCallback != null) { 47 | logCallback.logV("HMSAgent", sb.toString()); 48 | } else { 49 | Log.v("HMSAgent", sb.toString()); 50 | } 51 | } 52 | 53 | public static void i(String log) { 54 | StringBuilder sb = new StringBuilder(); 55 | appendStack(sb); 56 | sb.append(log); 57 | if (logCallback != null) { 58 | logCallback.logI("HMSAgent", sb.toString()); 59 | } else { 60 | Log.i("HMSAgent", sb.toString()); 61 | } 62 | } 63 | 64 | public static void w(String log) { 65 | StringBuilder sb = new StringBuilder(); 66 | appendStack(sb); 67 | sb.append(log); 68 | if (logCallback != null) { 69 | logCallback.logW("HMSAgent", sb.toString()); 70 | } else { 71 | Log.w("HMSAgent", sb.toString()); 72 | } 73 | } 74 | 75 | public static void e(String log) { 76 | StringBuilder sb = new StringBuilder(); 77 | appendStack(sb); 78 | sb.append(log); 79 | 80 | if (logCallback != null) { 81 | logCallback.logE("HMSAgent", sb.toString()); 82 | } else { 83 | Log.e("HMSAgent", sb.toString()); 84 | } 85 | } 86 | 87 | private static void appendStack(StringBuilder sb) { 88 | StackTraceElement[] stacks = Thread.currentThread().getStackTrace(); 89 | if (stacks != null && stacks.length > START_STACK_INDEX) { 90 | int lastIndex = Math.min(stacks.length-1,START_STACK_INDEX+PRINT_STACK_COUTN); 91 | for (int i=lastIndex; i >= START_STACK_INDEX; i--) { 92 | if (stacks[i] == null) { 93 | continue; 94 | } 95 | 96 | String fileName = stacks[i].getFileName(); 97 | if (fileName != null) { 98 | int dotIndx = fileName.indexOf('.'); 99 | if (dotIndx > 0) { 100 | fileName = fileName.substring(0, dotIndx); 101 | } 102 | } 103 | 104 | sb.append(fileName); 105 | sb.append('('); 106 | sb.append(stacks[i].getLineNumber()); 107 | sb.append(")"); 108 | sb.append("->"); 109 | } 110 | sb.append(stacks[START_STACK_INDEX].getMethodName()); 111 | } 112 | sb.append('\n'); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/IActivityDestroyedCallback.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * Activity onDestroyed 事件回调接口 7 | */ 8 | public interface IActivityDestroyedCallback { 9 | 10 | /** 11 | * Activity onPause回调 12 | * @param activityDestroyed 发生 onDestroyed 事件的activity 13 | * @param activityNxt 下个要显示的activity 14 | */ 15 | void onActivityDestroyed(Activity activityDestroyed, Activity activityNxt); 16 | } 17 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/IActivityPauseCallback.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * Activity onPause 事件回调接口 7 | */ 8 | public interface IActivityPauseCallback { 9 | 10 | /** 11 | * Activity onPause回调 12 | * @param activity 发生 onPause 事件的activity 13 | */ 14 | void onActivityPause(Activity activity); 15 | } 16 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/IActivityResumeCallback.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.app.Activity; 4 | 5 | /** 6 | * Activity onResume 事件回调接口 7 | */ 8 | public interface IActivityResumeCallback { 9 | 10 | /** 11 | * Activity onResume回调 12 | * @param activity 发生 onResume 事件的activity 13 | */ 14 | void onActivityResume(Activity activity); 15 | } 16 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/ICallbackCode.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 回调接口 5 | */ 6 | public interface ICallbackCode { 7 | /** 8 | * 回调接口 9 | * @param rst 结果码 10 | */ 11 | void onResult(int rst); 12 | } 13 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/ICallbackResult.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 回调接口 5 | */ 6 | public interface ICallbackResult { 7 | /** 8 | * 回调接口 9 | * @param rst 结果码 10 | * @param result 结果信息 11 | */ 12 | void onResult(int rst, R result); 13 | } 14 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/IClientConnectCallback.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import com.huawei.hms.api.HuaweiApiClient; 4 | 5 | /** 6 | * HuaweiApiClient 连接结果回调 7 | */ 8 | public interface IClientConnectCallback { 9 | /** 10 | * HuaweiApiClient 连接结果回调 11 | * @param rst 结果码 12 | * @param client HuaweiApiClient 实例 13 | */ 14 | void onConnect(int rst, HuaweiApiClient client); 15 | } 16 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/INoProguard.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 不混淆类 5 | */ 6 | public interface INoProguard { 7 | } 8 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/IOUtils.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | 6 | /** 7 | * 工具类 8 | */ 9 | public final class IOUtils { 10 | public static void close(Closeable object) { 11 | if (object != null) { 12 | try { 13 | object.close(); 14 | } catch (IOException e) { 15 | HMSAgentLog.d("close fail"); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/StrUtils.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | /** 4 | * 工具类 5 | */ 6 | public final class StrUtils { 7 | /** 8 | * 返回对象的描述,这里为了避免用户数据隐私的泄露,只是返回对象本身的描述 类名@hashcode 9 | * @param object 对象 10 | * @return 对象的描述 11 | */ 12 | public static String objDesc(Object object) { 13 | return object == null ? "null" : (object.getClass().getName()+'@'+Integer.toHexString(object.hashCode())); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/ThreadUtil.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | /** 10 | * 线程工具,用于执行线程等 11 | */ 12 | public final class ThreadUtil { 13 | public static final ThreadUtil INST = new ThreadUtil(); 14 | 15 | private ExecutorService executors; 16 | 17 | private ThreadUtil(){ 18 | } 19 | 20 | /** 21 | * 在线程中执行 22 | * @param runnable 要执行的runnable 23 | */ 24 | public void excute(Runnable runnable) { 25 | ExecutorService executorService = getExecutorService(); 26 | if (executorService != null) { 27 | // 优先使用线程池,提高效率 28 | executorService.execute(runnable); 29 | } else { 30 | // 线程池获取失败,则直接使用线程 31 | new Thread(runnable).start(); 32 | } 33 | } 34 | 35 | /** 36 | * 在主线程中执行 37 | * @param runnable 要执行的runnable 38 | */ 39 | public void excuteInMainThread(Runnable runnable){ 40 | new Handler(Looper.getMainLooper()).post(runnable); 41 | } 42 | 43 | /** 44 | * 获取缓存线程池 45 | * @return 缓存线程池服务 46 | */ 47 | private ExecutorService getExecutorService(){ 48 | if (executors == null) { 49 | try { 50 | executors = Executors.newCachedThreadPool(); 51 | } catch (Exception e) { 52 | HMSAgentLog.e("create thread service error:" + e.getMessage()); 53 | } 54 | } 55 | 56 | return executors; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/common/handler/ConnectHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.common.handler; 2 | 3 | /** 4 | * HuaweiApiClient 连接结果回调 5 | */ 6 | public interface ConnectHandler { 7 | /** 8 | * HuaweiApiClient 连接结果回调 9 | * @param rst 结果码 10 | */ 11 | void onConnect(int rst); 12 | } 13 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/DeleteTokenApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.text.TextUtils; 6 | 7 | import com.huawei.android.hms.agent.HMSAgent; 8 | import com.huawei.android.hms.agent.common.ApiClientMgr; 9 | import com.huawei.android.hms.agent.common.BaseApiAgent; 10 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 11 | import com.huawei.android.hms.agent.common.HMSAgentLog; 12 | import com.huawei.android.hms.agent.common.StrUtils; 13 | import com.huawei.android.hms.agent.common.ThreadUtil; 14 | import com.huawei.android.hms.agent.push.handler.DeleteTokenHandler; 15 | import com.huawei.hms.api.HuaweiApiClient; 16 | import com.huawei.hms.support.api.push.HuaweiPush; 17 | 18 | /** 19 | * 删除pushtoken的接口。 20 | */ 21 | public class DeleteTokenApi extends BaseApiAgent { 22 | 23 | /** 24 | * 待删除的push token 25 | */ 26 | private String token; 27 | 28 | /** 29 | * 调用接口回调 30 | */ 31 | private DeleteTokenHandler handler; 32 | 33 | /** 34 | * HuaweiApiClient 连接结果回调 35 | * 36 | * @param rst 结果码 37 | * @param client HuaweiApiClient 实例 38 | */ 39 | @Override 40 | public void onConnect(final int rst, final HuaweiApiClient client) { 41 | //需要在子线程中执行删除TOKEN操作 42 | ThreadUtil.INST.excute(new Runnable() { 43 | @Override 44 | public void run() { 45 | //调用删除TOKEN需要传入通过getToken接口获取到TOKEN,并且需要对TOKEN进行非空判断 46 | if (!TextUtils.isEmpty(token)){ 47 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 48 | HMSAgentLog.e("client not connted"); 49 | onDeleteTokenResult(rst); 50 | } else { 51 | try { 52 | HuaweiPush.HuaweiPushApi.deleteToken(client, token); 53 | onDeleteTokenResult(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS); 54 | } catch (Exception e) { 55 | HMSAgentLog.e("删除TOKEN失败:" + e.getMessage()); 56 | onDeleteTokenResult(HMSAgent.AgentResultCode.CALL_EXCEPTION); 57 | } 58 | } 59 | } else { 60 | HMSAgentLog.e("删除TOKEN失败: 要删除的token为空"); 61 | onDeleteTokenResult(HMSAgent.AgentResultCode.EMPTY_PARAM); 62 | } 63 | } 64 | }); 65 | } 66 | 67 | void onDeleteTokenResult(int rstCode) { 68 | HMSAgentLog.i("deleteToken:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 69 | if (handler != null) { 70 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 71 | handler = null; 72 | } 73 | } 74 | 75 | /** 76 | * 删除指定的pushtoken 77 | * 该接口只在EMUI5.1以及更高版本的华为手机上调用该接口后才不会收到PUSH消息。 78 | * @param token 要删除的token 79 | */ 80 | public void deleteToken(String token, DeleteTokenHandler handler) { 81 | HMSAgentLog.i("deleteToken:token:" + StrUtils.objDesc(token) + " handler=" + StrUtils.objDesc(handler)); 82 | this.token = token; 83 | this.handler = handler; 84 | connect(); 85 | } 86 | } -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/EnableReceiveNormalMsgApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.huawei.android.hms.agent.HMSAgent; 7 | import com.huawei.android.hms.agent.common.ApiClientMgr; 8 | import com.huawei.android.hms.agent.common.BaseApiAgent; 9 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 10 | import com.huawei.android.hms.agent.common.HMSAgentLog; 11 | import com.huawei.android.hms.agent.common.StrUtils; 12 | import com.huawei.android.hms.agent.common.ThreadUtil; 13 | import com.huawei.android.hms.agent.push.handler.EnableReceiveNormalMsgHandler; 14 | import com.huawei.hms.api.HuaweiApiClient; 15 | import com.huawei.hms.support.api.push.HuaweiPush; 16 | 17 | /** 18 | * 打开透传消息开关的接口。 19 | */ 20 | public class EnableReceiveNormalMsgApi extends BaseApiAgent { 21 | 22 | /** 23 | * 是否打开开关 24 | */ 25 | boolean enable; 26 | 27 | /** 28 | * 调用接口回调 29 | */ 30 | private EnableReceiveNormalMsgHandler handler; 31 | 32 | /** 33 | * HuaweiApiClient 连接结果回调 34 | * 35 | * @param rst 结果码 36 | * @param client HuaweiApiClient 实例 37 | */ 38 | @Override 39 | public void onConnect(final int rst, final HuaweiApiClient client) { 40 | //需要在子线程中执行开关的操作 41 | ThreadUtil.INST.excute(new Runnable() { 42 | @Override 43 | public void run() { 44 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 45 | HMSAgentLog.e("client not connted"); 46 | onEnableReceiveNormalMsgResult(rst); 47 | } else { 48 | // 开启/关闭透传消息 49 | HuaweiPush.HuaweiPushApi.enableReceiveNormalMsg(client, enable); 50 | onEnableReceiveNormalMsgResult(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS); 51 | } 52 | } 53 | }); 54 | } 55 | 56 | void onEnableReceiveNormalMsgResult(int rstCode) { 57 | HMSAgentLog.i("enableReceiveNormalMsg:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 58 | if (handler != null) { 59 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 60 | handler = null; 61 | } 62 | } 63 | 64 | /** 65 | * 打开/关闭透传消息 66 | * @param enable 打开/关闭 67 | */ 68 | public void enableReceiveNormalMsg(boolean enable, EnableReceiveNormalMsgHandler handler) { 69 | HMSAgentLog.i("enableReceiveNormalMsg:enable=" + enable + " handler=" + StrUtils.objDesc(handler)); 70 | this.enable = enable; 71 | this.handler = handler; 72 | connect(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/EnableReceiveNotifyMsgApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.huawei.android.hms.agent.HMSAgent; 7 | import com.huawei.android.hms.agent.common.ApiClientMgr; 8 | import com.huawei.android.hms.agent.common.BaseApiAgent; 9 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 10 | import com.huawei.android.hms.agent.common.HMSAgentLog; 11 | import com.huawei.android.hms.agent.common.StrUtils; 12 | import com.huawei.android.hms.agent.common.ThreadUtil; 13 | import com.huawei.android.hms.agent.push.handler.EnableReceiveNotifyMsgHandler; 14 | import com.huawei.hms.api.HuaweiApiClient; 15 | import com.huawei.hms.support.api.push.HuaweiPush; 16 | 17 | /** 18 | * 打开自呈现消息开关的接口。 19 | */ 20 | public class EnableReceiveNotifyMsgApi extends BaseApiAgent { 21 | 22 | /** 23 | * 是否打开开关 24 | */ 25 | boolean enable; 26 | 27 | /** 28 | * 调用接口回调 29 | */ 30 | private EnableReceiveNotifyMsgHandler handler; 31 | 32 | /** 33 | * HuaweiApiClient 连接结果回调 34 | * 35 | * @param rst 结果码 36 | * @param client HuaweiApiClient 实例 37 | */ 38 | @Override 39 | public void onConnect(final int rst, final HuaweiApiClient client) { 40 | //需要在子线程中执行开关的操作 41 | ThreadUtil.INST.excute(new Runnable() { 42 | @Override 43 | public void run() { 44 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 45 | HMSAgentLog.e("client not connted"); 46 | onEnableReceiveNotifyMsgResult(rst); 47 | } else { 48 | // 开启/关闭自呈现消息 49 | HuaweiPush.HuaweiPushApi.enableReceiveNotifyMsg(client, enable); 50 | onEnableReceiveNotifyMsgResult(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS); 51 | } 52 | } 53 | }); 54 | } 55 | 56 | void onEnableReceiveNotifyMsgResult(int rstCode) { 57 | HMSAgentLog.i("enableReceiveNotifyMsg:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 58 | if (handler != null) { 59 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 60 | handler = null; 61 | } 62 | } 63 | 64 | /** 65 | * 打开/关闭自呈现消息 66 | * @param enable 打开/关闭 67 | */ 68 | public void enableReceiveNotifyMsg(boolean enable, EnableReceiveNotifyMsgHandler handler) { 69 | HMSAgentLog.i("enableReceiveNotifyMsg:enable=" + enable + " handler=" + StrUtils.objDesc(handler)); 70 | this.enable = enable; 71 | this.handler = handler; 72 | connect(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/GetPushStateApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.huawei.android.hms.agent.HMSAgent; 7 | import com.huawei.android.hms.agent.common.ApiClientMgr; 8 | import com.huawei.android.hms.agent.common.BaseApiAgent; 9 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 10 | import com.huawei.android.hms.agent.common.HMSAgentLog; 11 | import com.huawei.android.hms.agent.common.StrUtils; 12 | import com.huawei.android.hms.agent.common.ThreadUtil; 13 | import com.huawei.android.hms.agent.push.handler.GetPushStateHandler; 14 | import com.huawei.hms.api.HuaweiApiClient; 15 | import com.huawei.hms.support.api.push.HuaweiPush; 16 | 17 | /** 18 | * 获取push状态的接口。 19 | */ 20 | public class GetPushStateApi extends BaseApiAgent { 21 | 22 | /** 23 | * 调用接口回调 24 | */ 25 | private GetPushStateHandler handler; 26 | 27 | /** 28 | * HuaweiApiClient 连接结果回调 29 | * 30 | * @param rst 结果码 31 | * @param client HuaweiApiClient 实例 32 | */ 33 | @Override 34 | public void onConnect(final int rst, final HuaweiApiClient client) { 35 | //需要在子线程中执行获取push状态的操作 36 | ThreadUtil.INST.excute(new Runnable() { 37 | @Override 38 | public void run() { 39 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 40 | HMSAgentLog.e("client not connted"); 41 | onGetPushStateResult(rst); 42 | } else { 43 | HuaweiPush.HuaweiPushApi.getPushState(client); 44 | onGetPushStateResult(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS); 45 | } 46 | } 47 | }); 48 | } 49 | 50 | void onGetPushStateResult(int rstCode) { 51 | HMSAgentLog.i("getPushState:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 52 | if (handler != null) { 53 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 54 | handler = null; 55 | } 56 | } 57 | 58 | /** 59 | * 获取push状态,push状态的回调通过广播发送。 60 | * 要监听的广播,请参见HMS-SDK开发准备中PushReceiver的注册 61 | */ 62 | public void getPushState(GetPushStateHandler handler) { 63 | HMSAgentLog.i("getPushState:handler=" + StrUtils.objDesc(handler)); 64 | this.handler = handler; 65 | connect(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/GetTokenApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.huawei.android.hms.agent.HMSAgent; 7 | import com.huawei.android.hms.agent.common.ApiClientMgr; 8 | import com.huawei.android.hms.agent.common.BaseApiAgent; 9 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 10 | import com.huawei.android.hms.agent.common.HMSAgentLog; 11 | import com.huawei.android.hms.agent.common.StrUtils; 12 | import com.huawei.android.hms.agent.push.handler.GetTokenHandler; 13 | import com.huawei.hms.api.HuaweiApiClient; 14 | import com.huawei.hms.support.api.client.PendingResult; 15 | import com.huawei.hms.support.api.client.ResultCallback; 16 | import com.huawei.hms.support.api.client.Status; 17 | import com.huawei.hms.support.api.entity.core.CommonCode; 18 | import com.huawei.hms.support.api.push.HuaweiPush; 19 | import com.huawei.hms.support.api.push.TokenResult; 20 | 21 | /** 22 | * 获取token的push接口,token的结果通过广播进行接收。 23 | */ 24 | public class GetTokenApi extends BaseApiAgent { 25 | 26 | /** 27 | * client 无效最大尝试次数 28 | */ 29 | private static final int MAX_RETRY_TIMES = 1; 30 | 31 | /** 32 | * 结果回调 33 | */ 34 | private GetTokenHandler handler; 35 | 36 | /** 37 | * 当前剩余重试次数 38 | */ 39 | private int retryTimes = MAX_RETRY_TIMES; 40 | 41 | /** 42 | * HuaweiApiClient 连接结果回调 43 | * 44 | * @param rst 结果码 45 | * @param client HuaweiApiClient 实例 46 | */ 47 | @Override 48 | public void onConnect(int rst, HuaweiApiClient client) { 49 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 50 | HMSAgentLog.e("client not connted"); 51 | onPushTokenResult(rst, null); 52 | return; 53 | } 54 | 55 | PendingResult tokenResult = HuaweiPush.HuaweiPushApi.getToken(client); 56 | tokenResult.setResultCallback(new ResultCallback() { 57 | @Override 58 | public void onResult(TokenResult result) { 59 | if (result == null) { 60 | HMSAgentLog.e("result is null"); 61 | onPushTokenResult(HMSAgent.AgentResultCode.RESULT_IS_NULL, null); 62 | return; 63 | } 64 | 65 | Status status = result.getStatus(); 66 | if (status == null) { 67 | HMSAgentLog.e("status is null"); 68 | onPushTokenResult(HMSAgent.AgentResultCode.STATUS_IS_NULL, null); 69 | return; 70 | } 71 | 72 | int rstCode = status.getStatusCode(); 73 | HMSAgentLog.d("rstCode=" + rstCode); 74 | // 需要重试的错误码,并且可以重试 75 | if ((rstCode == CommonCode.ErrorCode.SESSION_INVALID 76 | || rstCode == CommonCode.ErrorCode.CLIENT_API_INVALID) && retryTimes > 0) { 77 | retryTimes--; 78 | connect(); 79 | } else { 80 | onPushTokenResult(rstCode, result); 81 | } 82 | } 83 | }); 84 | } 85 | 86 | /** 87 | * 获取pushtoken接口调用回调 88 | * pushtoken通过广播下发,要监听的广播,请参见HMS-SDK开发准备中PushReceiver的注册 89 | * @param rstCode 结果码 90 | * @param result 调用获取pushtoken接口的结果 91 | */ 92 | void onPushTokenResult(int rstCode, TokenResult result) { 93 | HMSAgentLog.i("getToken:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 94 | if (handler != null) { 95 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 96 | handler = null; 97 | } 98 | retryTimes = MAX_RETRY_TIMES; 99 | } 100 | 101 | /** 102 | * 获取pushtoken接口 103 | * pushtoken通过广播下发,要监听的广播,请参见HMS-SDK开发准备中PushReceiver的注册 104 | * @param handler pushtoken接口调用回调 105 | */ 106 | public void getToken(GetTokenHandler handler) { 107 | HMSAgentLog.i("getToken:handler=" + StrUtils.objDesc(handler)); 108 | this.handler = handler; 109 | retryTimes = MAX_RETRY_TIMES; 110 | connect(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/QueryAgreementApi.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import com.huawei.android.hms.agent.HMSAgent; 7 | import com.huawei.android.hms.agent.common.ApiClientMgr; 8 | import com.huawei.android.hms.agent.common.BaseApiAgent; 9 | import com.huawei.android.hms.agent.common.CallbackCodeRunnable; 10 | import com.huawei.android.hms.agent.common.HMSAgentLog; 11 | import com.huawei.android.hms.agent.common.StrUtils; 12 | import com.huawei.android.hms.agent.common.ThreadUtil; 13 | import com.huawei.android.hms.agent.push.handler.QueryAgreementHandler; 14 | import com.huawei.hms.api.HuaweiApiClient; 15 | import com.huawei.hms.support.api.push.HuaweiPush; 16 | 17 | /** 18 | * 获取push协议展示的接口。 19 | */ 20 | public class QueryAgreementApi extends BaseApiAgent { 21 | 22 | /** 23 | * 调用接口回调 24 | */ 25 | private QueryAgreementHandler handler; 26 | 27 | /** 28 | * HuaweiApiClient 连接结果回调 29 | * 30 | * @param rst 结果码 31 | * @param client HuaweiApiClient 实例 32 | */ 33 | @Override 34 | public void onConnect(final int rst, final HuaweiApiClient client) { 35 | //需要在子线程中执行获取push协议展示的操作 36 | ThreadUtil.INST.excute(new Runnable() { 37 | @Override 38 | public void run() { 39 | if (client == null || !ApiClientMgr.INST.isConnect(client)) { 40 | HMSAgentLog.e("client not connted"); 41 | onQueryAgreementResult(rst); 42 | } else { 43 | HuaweiPush.HuaweiPushApi.queryAgreement(client); 44 | onQueryAgreementResult(HMSAgent.AgentResultCode.HMSAGENT_SUCCESS); 45 | } 46 | } 47 | }); 48 | } 49 | 50 | void onQueryAgreementResult(int rstCode) { 51 | HMSAgentLog.i("queryAgreement:callback=" + StrUtils.objDesc(handler) +" retCode=" + rstCode); 52 | if (handler != null) { 53 | new Handler(Looper.getMainLooper()).post(new CallbackCodeRunnable(handler, rstCode)); 54 | handler = null; 55 | } 56 | } 57 | 58 | /** 59 | * 请求push协议展示 60 | */ 61 | public void queryAgreement(QueryAgreementHandler handler) { 62 | HMSAgentLog.i("queryAgreement:handler=" + StrUtils.objDesc(handler)); 63 | this.handler = handler; 64 | connect(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/DeleteTokenHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * deleteToken 回调 7 | */ 8 | public interface DeleteTokenHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/EnableReceiveNormalMsgHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * enableReceiveNormalMsg 回调 7 | */ 8 | public interface EnableReceiveNormalMsgHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/EnableReceiveNotifyMsgHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * enableReceiveNotifyMsg 回调 7 | */ 8 | public interface EnableReceiveNotifyMsgHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/GetPushStateHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * getPushState 回调 7 | */ 8 | public interface GetPushStateHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/GetTokenHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * 获取 pushtoken 回调 7 | */ 8 | public interface GetTokenHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/java/com/huawei/android/hms/agent/push/handler/QueryAgreementHandler.java: -------------------------------------------------------------------------------- 1 | package com.huawei.android.hms.agent.push.handler; 2 | 3 | import com.huawei.android.hms.agent.common.ICallbackCode; 4 | 5 | /** 6 | * queryAgreement 回调 7 | */ 8 | public interface QueryAgreementHandler extends ICallbackCode { 9 | } 10 | -------------------------------------------------------------------------------- /push/src/main/res/values-zh-rCN/hms_values-zh-rCN.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /push/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /push/src/main/res/values/hms_values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /push/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | push 3 | 4 | -------------------------------------------------------------------------------- /push/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /pushdemo.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Luomingbear/Push/49c3e097f97f403eec6ed903a4a81ca3044ec844/pushdemo.jks -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Push 3 | 4 | 一个推送的模块,集成了华为、小米、魅族、OPPO和极光推送,根据设备厂商判断使用具体哪个SDK如:小米手机使用小米推送,华为手机使用华为推送,其他的设备使用极光推送。 5 | 6 | ## 更新时间 7 | 8 | 2019/07/4 9 | 10 | 添加统一接收消息的`BasePushBroadcastReceiver`和vivo推送平台 11 | 12 | ## 使用 13 | 14 | ### 1.配置AppKey 15 | 16 | 在您的app 的gradle配置文件里面添加如下代码: 17 | 18 | ```groovy 19 | defaultConfig { 20 | manifestPlaceholders = [ 21 | "jPushAppkey" : "ea6c961e572ad972df4ef456",//极光推送的AppKey 22 | "huaweiPushAppId" : "100698925",//华为推送的AppId 23 | "xiaomiPushAppkey": "55617974 54571",//"57417800 14675",//小米推送的AppKey****请务必在数值中间添加一个空格,否则会发生数值变化**** 24 | "xiaomiPushAppId" : "28823037 61517974571",//"28823037 61517800675",//小米推送的AppID****请务必在数值中间添加一个空格,否则会发生数值变化**** 25 | "oppoAppKey" : "9d24177594c741be86465ec9fe490a44",//OPPO推送的appKey 26 | "oppoAppSecret" : "c60bec1f803e49e88037562ec2109286",//OPPO推送的appSecret 27 | "meizuAppId" : "1200 55",//魅族推送AppId ****请务必在数值中间添加一个空格,否则会发生数值变化**** 28 | "meizuAppKey" : "3aca7449444347c4a1d2a70826ae1e9b",//魅族推送AppKey 29 | "vivoAppId" : "11937",//vivo推送AppId 30 | "vivoAppKey" : "acfdb480-e178-4098-80ae-76284df7d588",//vivo推送AppKey 31 | "marketChannel" : "develops"//渠道 32 | ] 33 | } 34 | ``` 35 | 36 | 在push模块下面的`buid.gradle`文件里面替换对应的AppKey,**需要注意的地方**: 37 | 38 | > 小米的AppKey和魅族的AppId是使用的数字的格式,不能直接复制粘粘到文件里面,需要在中间增加一个空格,例如:AppKey为`201584151343514321321`需要替换为`20158415134 3514321321` 39 | 40 | ### 2.配置华为推送 41 | 42 | 华为推送的SDK是通过工具生成的,所以需要手动配置生成代码,先[下载华为HMS Agent套件](https://obs.cn-north-2.myhwclouds.com/hms-ds-wf/sdk/HMSAgent_2.6.1.302.zip),解压出来之后根据自己的电脑系统需要相应的脚本文件,例如:Window点击双击`GetHMSAgent_cn.bat`在弹出的窗口里面根据提示操作就好了,最后生存的代码会保存在`copysrc`文件夹里面。将生成的代码复制到Push的java目录下面,res资源文件根据需要添加到资源目录下。 43 | 44 | ### 3.初始化 45 | 46 | 在Application的onCreate里面调用`PushTargetManager`的`init`方法。 47 | 48 | ### 4.处理推送消息 49 | 50 | 推送的信息分为`Message`和`Notification`,Notification会主动在通知栏显示通知,而Message不会。 51 | 52 | 要处理接收到的信息,只需要实现`BasePushBroadcastReceiver`或者`PushTargetManager.getInstance().addPushReceiverListener(String, OnPushReceiverListener)`方法即可。 53 | 54 | #### 4.1自定义BasePushBroadcastReceiver 55 | 56 | ```java 57 | PushBroadcastReceiverIml extends BasePushBroadcastReceiver{ 58 | 59 | public PushBroadcastReceiverIml() { 60 | } 61 | 62 | @Override 63 | public void onRegister(Context context, ReceiverInfo info) { 64 | Log.d(TAG, "推送注册成功\n" + info.toString()); 65 | } 66 | 67 | @Override 68 | public void onAlias(Context context, ReceiverInfo info) { 69 | Log.d(TAG, "设置了别名\n" + info.toString()); 70 | } 71 | 72 | @Override 73 | public void onMessage(Context context, ReceiverInfo info) { 74 | Log.d(TAG, "收到自定义消息\n" + info.toString()); 75 | } 76 | 77 | @Override 78 | public void onNotification(Context context, ReceiverInfo info) { 79 | Log.d(TAG, "收到通知\n" + info.toString()); 80 | } 81 | 82 | @Override 83 | public void onOpened(Context context, ReceiverInfo info) { 84 | Log.d(TAG, "点击了通知\n" + info.toString()); 85 | } 86 | } 87 | ``` 88 | 89 | 在`manifest`里面注册广播接收器 90 | 91 | ```xml 92 | 93 | 96 | 97 | 98 | 99 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | ``` 109 | 110 | #### 4.2addPushReceiverListener() 111 | 112 | ```java 113 | PushTargetManager.getInstance().addPushReceiverListener("ml", 114 | new PushTargetManager.OnPushReceiverListener() { 115 | @Override 116 | public void onRegister(ReceiverInfo info) { 117 | Log.d(TAG, "注册成功\n" + info.toString()); 118 | } 119 | 120 | @Override 121 | public void onAlias(ReceiverInfo info) { 122 | Log.d(TAG, "设置了别名\n" + info.toString()); 123 | } 124 | 125 | @Override 126 | public void onMessage(ReceiverInfo info) { 127 | Log.d(TAG, "收到了自定义消息\n" + info.toString()); 128 | } 129 | 130 | @Override 131 | public void onNotification(ReceiverInfo info) { 132 | Log.d(TAG, "收到了通知\n" + info.toString()); 133 | } 134 | 135 | @Override 136 | public void onOpened(ReceiverInfo info) { 137 | Log.d(TAG, "点击通知\n" + info.toString()); 138 | } 139 | }); 140 | ``` 141 | 142 | **注意**:*使用这种方式有一个局限,就是只会在应用运行期间有回调,应用杀死之后就不会有反应了,所以推荐使用第一种方式。* 143 | 144 | ### 5.处理用户点击通知栏 145 | 146 | 针对用户点击通知栏的行为,我们可能需要对通知进行处理跳转到指定的页面。当有用户点击通知栏的时候`BasePushBroadcastReceiver`或者`OnPushReceiverListener`的`onOpened(Context context, ReceiverInfo info)`会执行,我们只需要在这里处理就可以了。**需要注意的是,华为和OPPO的事件处理使用的是一个虚拟的Activity进行中转。 **因为无法监听到用户点击的事件,但是可以在点击之后打开的页面里面获取到传递的数据,间接的进行处理。所以使用的时候需要和后端协商好推送类型为自定义参数的格式。 147 | 148 | > OPPO和华为的处理Activity分别为`OppoLoadActivity`、`HuaweiLoadActivity`具体的intent设置请按照自己的需求修改。 149 | 150 | ![微信截图_20180530160745](img/微信截图_20180531111009.png) 151 | 152 | ### 6.设置别名 153 | 154 | 为了区别不同的设备与账号的对应关系,需要将设备别名设置到推送服务器和自己应用的服务器。* 当然,如果你不需要知道具体用户对于的设备,也可以不处理 *。 **别名的设置需要执行`PushTargetManager`的`setAlias`, **建议在注册成功之后再执行设置别名的操作,即在`HandleReceiverRegistration`的`handle`里面执行。 **需要注意的是华为推送不支持设置别名,只能获取华为服务器返回的`token` **。对于将别名上传到服务器的操作,用户只需要在`HandleReceiverAlias`类实现`handle`方法就可以了。 155 | 156 | ![微信截图_20180530152949](img/微信截图_20180531111115.png) 157 | 158 | ### 7.获取注册id 159 | 160 | 在`BasePushBroadcastReceiver`或者`OnPushReceiverListener`的`onRegister(Context context, ReceiverInfo info)`会在推送sdk注册成功之后回调,所以,可以在这里获取注册id,此时的`ReceiverInfo`数据结构如下: 161 | 162 | | pushTarget | PushTargetEnum的枚举,表示了当前的推送平台 | 163 | | ---------- | ------------------------------------------ | 164 | | title | 提示文本,例如“小米推送注册成功” | 165 | | content | 注册id | 166 | | rawData | 推送平台注册成功之后的原始返回值 | 167 | 168 | ## 模块设计思路 169 | 170 | 通过对推送服务的分析,我将推送分为了三个步骤,分别是:初始化、接收和处理,不同的推送平台的接收方式并不一样,但是推送服务只是一个工具,接收推送之后的处理才是关键,而这个是不需要根据不同的平台来变化的,所以我使用了一个统一的处理入口。 171 | 172 | ![PushMind](img/PushMind.png) 173 | 174 | 根据这个思路,我设计的代码结构如下: 175 | 176 | ![folder](img/folder.png) 177 | 178 | | 目录 | 说明 | 179 | | ------ | ---------------------------------- | 180 | | Handle | 统一处理接收到的推送信息 | 181 | | Target | 将不同的推送平台的初始化和接收存放在这个目录里面,按照推送平台分类。 | 182 | 183 | 关于消息的处理,通常会有:SDK注册成功、接收到消息、用户点击通知栏等,所以我将不同的动作分配到具体的类里面,减少一个大类处理多个方法的问题,通过一个入口类管理具体的行为。 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':push' 2 | --------------------------------------------------------------------------------