- 官方文档:https://www.jiguang.cn/push
- SDK下载:http://docs.jiguang.cn/jpush/resources/
- 官方Github:https://github.com/jpush
这篇文章主要介绍是怎么使用极光推送
其他文章:
推送是用来干嘛的?
如图:
如何即使获取服务器上的信息?
-
定时轮询:
- 实现简单
- 时效性不高
- 耗电、耗流量
示意图:
-
使用推送:
- 实现复杂
- 时效性高
- 省电、省流量
示意图:
常见的推送方式
- 一、Google提供的C2DM服务
- 二、使用MMQT协议实现android推送功能
- 三、使用XMPP协议实现android推送功能
- 四、第三方平台
- 极光推送
- 百度云推送
- 友盟
极光推送的使用方法:
第一步:登录极光推送的官网:https://www.jiguang.cn/
第二步:通过邮箱(尽量不用qq邮箱)注册登录
第三步:打开Android Studio 新建一个工程,记住包名,默认点击finish即可
- 我这里的包名是:com.demo.jpdemo
第四步:登录成功后,进入极光推送的开发者服务页 这里是网址:https://www.jiguang.cn/dev/#/app/list#dev
第五步:创建应用
点击应用管理——>创建应用——>输入应用的名称(任意)
应用创建成功后:有两个比较重要的东西 记住
- AppKey:客户端使用的
- Master Secret :想自己实现服务器时使用
页面往下拉,看到推送设置,点击完成推送设置
选择Android平台,写上应用包名! 必须和你的工程的包名一致,然后点击完成即可
第六步:下载极光推送的Android的SDK 这是地址:https://docs.jiguang.cn/jpush/resources/
下载完成后解压:
目录结构:
- AndroidManifest.xml
- 客户端嵌入 SDK 参考的配置文件
- libs/jcore-android.1.x.x.jar
- 极光开发者服务的核心包。
- libs/jpush-android-3.x.y.jar
- JPush SDK 开发包。
- libs/(cpu-type)/libjcore1xx.so
- 各种 CPU 类型的 native 开发包。
- res
- 集成 SDK 必须添加的资源文件
- example
- 是一个完整的 Android 项目,通过这个演示了 JPush SDK 的基本用法,可以用来做参考。
第七步:将SDK集成到你的工程当中
可以根据开发文档走:https://docs.jiguang.cn/jpush/client/Android/android_guide/
也可以按照我下面粗暴的方法来:
打开刚刚新建好的工程,将SDK中对应的libs包里面所有的文件拷贝工程的libs里面
拷贝成功后,选中 jpush-android-3.1.8.jar 右键 Add as Library 添加到模块的库中
实际就是模块的在build.gradle中添加了一行代码:
implementation files('libs/jpush-android-3.1.8.jar')
然后:在模块的build.gradle 添加以下一块代码,Sync 同步一下
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.demo.jpushdemo"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//添加这一块代码:这是添加Jni的库
sourceSets {
main {
jniLibs.srcDir("libs")
}
}
}
同步完成后,将SDK目录下的res目录复制替换工程里面的res目录(实际就是将SDK目录下的文件添加到工程的res目录下)
就是极光推送的界面布局文件
第八步:配置AndroidManifest.xml文件
以下是工程原生的AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo.jpdemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
以下是SDK里面的AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="您应用的包名"
android:versionCode="318"
android:versionName="3.1.8"
>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21" />
<!-- Required -->
<permission
android:name="您应用的包名.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" />
<!-- Required 一些系统要求的权限,如访问网络等-->
<uses-permission android:name="您应用的包名.permission.JPUSH_MESSAGE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- Optional for location -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application
android:icon="@drawable/ic_launcher"
android:allowBackup="false"
android:label="@string/app_name"
android:name="com.example.jpushdemo.ExampleApplication">
<!-- For test only 测试的主程序-->
<activity
android:name="com.example.jpushdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- For test only 测试高级功能 -->
<activity android:name="com.example.jpushdemo.PushSetActivity" android:label="@string/app_name"></activity>
<!-- For test only 测试设置 -->
<activity android:name="com.example.jpushdemo.SettingActivity" android:label="@string/app_name"></activity>
<!-- For test only 测试状态通知栏,需要打开的Activity -->
<activity android:name="com.example.jpushdemo.TestActivity" android:exported="false">
<intent-filter>
<action android:name="jpush.testAction" />
<category android:name="jpush.testCategory" />
</intent-filter>
</activity>
<!-- Rich push 核心功能 since 2.0.6-->
<activity
android:name="cn.jpush.android.ui.PopWinActivity"
android:theme="@style/MyDialogStyle"
android:exported="false">
</activity>
<!-- Required SDK核心功能-->
<activity
android:name="cn.jpush.android.ui.PushActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.NoTitleBar"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.ui.PushActivity" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="您应用的包名" />
</intent-filter>
</activity>
<!-- Required SDK 核心功能-->
<!-- 可配置android:process参数将PushService放在其他进程中 -->
<service
android:name="cn.jpush.android.service.PushService"
android:process=":pushcore"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTER" />
<action android:name="cn.jpush.android.intent.REPORT" />
<action android:name="cn.jpush.android.intent.PushService" />
<action android:name="cn.jpush.android.intent.PUSH_TIME" />
</intent-filter>
</service>
<!-- since 3.0.9 Required SDK 核心功能-->
<provider
android:authorities="您应用的包名.DataProvider"
android:name="cn.jpush.android.service.DataProvider"
android:process=":pushcore"
android:exported="false"
/>
<!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 -->
<!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 -->
<service
android:name="cn.jpush.android.service.DaemonService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="cn.jpush.android.intent.DaemonService" />
<category android:name="您应用的包名" />
</intent-filter>
</service>
<!-- since 3.1.0 Required SDK 核心功能-->
<provider
android:authorities="您应用的包名.DownloadProvider"
android:name="cn.jpush.android.service.DownloadProvider"
android:exported="true"
/>
<!-- Required SDK核心功能-->
<receiver
android:name="cn.jpush.android.service.PushReceiver"
android:enabled="true"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 显示通知栏 -->
<category android:name="您应用的包名" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<!-- Optional -->
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<!-- Required SDK核心功能-->
<receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/>
<!-- User defined. For test only 用户自定义的广播接收器-->
<receiver
android:name="com.example.jpushdemo.MyReceiver"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required 用户注册SDK的intent-->
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required 用户接收SDK消息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required 用户接收SDK通知栏信息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required 用户打开自定义通知栏的intent-->
<action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 -->
<category android:name="您应用的包名" />
</intent-filter>
</receiver>
<!-- User defined. For test only 用户自定义接收消息器,3.0.7开始支持,目前新tag/alias接口设置结果会在该广播接收器对应的方法中回调-->
<receiver android:name="com.example.jpushdemo.MyJPushMessageReceiver">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<category android:name="您应用的包名"></category>
</intent-filter>
</receiver>
<!-- Required . Enable it you can get statistics data with channel -->
<meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
<meta-data android:name="JPUSH_APPKEY" android:value="您应用的Appkey" /> <!-- </>值来自开发者平台取得的AppKey-->
</application>
</manifest>
简单粗暴的方法,直接将SDK中的AndroidManifest.xml替换原生的文件
你也可以根据下面的方法来配置
根据 SDK 压缩包里的 AndroidManifest.xml 样例文件,来配置应用程序项目的 AndroidManifest.xml 。
主要步骤为:
- 复制备注为 "Required" 的部分
- 将标注为“您应用的包名”的部分,替换为当前应用程序的包名
- 将标注为“您应用的 Appkey” 的部分,替换为在 Portal 上创建该应用后应用信息中的 Appkey,例如:9fed5bcb7b9b87413678c407
小帖士
如果使用 android studio,可在 AndroidManifest 中引用 applicationId 的值,在 build.gradle 配置中 defaultConfig 节点下配置,如:
defaultConfig { applicationId "cn.jpush.example" // <--您应用的包名 …… }
在 AndroidManifest 中使用 ${applicationId} 引用 gradle 中定义的包名
替换好原生的配置文件后,根据上面的小贴士,在build.gradle中定义好包名方便引用
其实默认是有这个 applicationId的
defaultConfig {
applicationId "com.demo.jpdemo"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
- 将涉及有包名的改成自己的包名
- 删除一些带有 only test 标签的
- 添加之前创建好应用的AppKey
- 创建一个MyApplication.java类 初始化
- 创建一个MyReciver.java 接受发过来的信息
以下是修改好后的配置文件:
看我上面写要修改的注释 一一比对
<?xml version="1.0" encoding="utf-8"?>
<!--修改:包名1-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo.jpdemo"
android:versionCode="318"
android:versionName="3.1.8"
>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21" />
<!--修改:包名2-->
<!-- Required -->
<permission
android:name="com.demo.jpdemo.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" />
<!--修改:包名3-->
<!-- Required 一些系统要求的权限,如访问网络等-->
<uses-permission android:name="com.demo.jpdemo.permission.JPUSH_MESSAGE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- Optional for location -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<!--修改:包名4-->
<application
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="com.demo.jpdemo.MyApplication">
<!--修改:包名5-->
<!-- For test only 测试的主程序-->
<activity
android:name="com.demo.jpdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Rich push 核心功能 since 2.0.6-->
<activity
android:name="cn.jpush.android.ui.PopWinActivity"
android:theme="@style/MyDialogStyle"
android:exported="false">
</activity>
<!-- Required SDK核心功能-->
<activity
android:name="cn.jpush.android.ui.PushActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.NoTitleBar"
android:exported="false">
<!--修改:包名6-->
<intent-filter>
<action android:name="cn.jpush.android.ui.PushActivity" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="${applicationId}" />
</intent-filter>
</activity>
<!-- Required SDK 核心功能-->
<!-- 可配置android:process参数将PushService放在其他进程中 -->
<service
android:name="cn.jpush.android.service.PushService"
android:process=":pushcore"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTER" />
<action android:name="cn.jpush.android.intent.REPORT" />
<action android:name="cn.jpush.android.intent.PushService" />
<action android:name="cn.jpush.android.intent.PUSH_TIME" />
</intent-filter>
</service>
<!--修改:包名7-->
<!-- since 3.0.9 Required SDK 核心功能-->
<provider
android:authorities="com.demo.jpdemo.DataProvider"
android:name="cn.jpush.android.service.DataProvider"
android:process=":pushcore"
android:exported="false"
/>
<!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 -->
<!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 -->
<service
android:name="cn.jpush.android.service.DaemonService"
android:enabled="true"
android:exported="true">
<!--修改:包名8-->
<intent-filter>
<action android:name="cn.jpush.android.intent.DaemonService" />
<category android:name="${applicationId}" />
</intent-filter>
</service>
<!--修改:包名9-->
<!-- since 3.1.0 Required SDK 核心功能-->
<provider
android:authorities="com.demo.jpdemo.DownloadProvider"
android:name="cn.jpush.android.service.DownloadProvider"
android:exported="true"
/>
<!-- Required SDK核心功能-->
<receiver
android:name="cn.jpush.android.service.PushReceiver"
android:enabled="true"
android:exported="false">
<!--修改:包名10-->
<intent-filter android:priority="1000">
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 显示通知栏 -->
<category android:name="${applicationId}" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<!-- Optional -->
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<!-- Required SDK核心功能-->
<receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/>
<!--修改:包名11-->
<!-- User defined. For test only 用户自定义的广播接收器-->
<receiver
android:name="com.demo.jpdemo.MyReceiver"
android:exported="false"
android:enabled="true">
<!--修改:包名12-->
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required 用户注册SDK的intent-->
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required 用户接收SDK消息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required 用户接收SDK通知栏信息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required 用户打开自定义通知栏的intent-->
<action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 -->
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<!--修改:添加appkey 13-->
<!-- Required . Enable it you can get statistics data with channel -->
<meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
<meta-data android:name="JPUSH_APPKEY" android:value="afeeb844639923ab08554464" /> <!-- </>值来自开发者平台取得的AppKey-->
</application>
</manifest>
MyApplication.java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化极光推送
JPushInterface.init(this);
//开启调试的模式
JPushInterface.setDebugMode(true);
}
}
MyReceiver.java
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "JPUSH---";
//在onReceive中接收发过来的消息
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//打印当前action
Log.e(TAG, "onReceive:" + action);
Bundle extras = intent.getExtras();
//如果是发通知的action
if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) {
//通知的内容
String alert = extras.getString(JPushInterface.EXTRA_ALERT);
//通知标题
String title = extras.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
Log.e(TAG, "onReceive" + ":通知的内容为:" + alert + ",通知的标题为:" + title);
}
//如果是自定义消息的action
else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) {
//自定义消息,没有通知栏
String msg = extras.getString(JPushInterface.EXTRA_MESSAGE);
Log.e(TAG, "onReceive" + ":自定义消息为:" + msg);
}
//如果是用点击了通知的action 打开当前activity
else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) {
//如果是点击通知栏的动作
//点击后跳转
Intent intent1 = new Intent(context, MainActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
}
}
看logcat:
如果出现错误:看Logcat的提示:https://docs.jiguang.cn/jpush/client/Android/android_faq/ 看官方问题
检查包名是否和注册的一致,还有配置文件的所有都填写正确,一般都是填写错误, 或者哪里忘记了添加
显示注册,并且链接上了(证明成功啦)
/com.demo.jpdemo E/JPUSH---: onReceive:cn.jpush.android.intent.REGISTRATION
/com.demo.jpdemo E/JPUSH---: onReceive:cn.jpush.android.intent.CONNECTION
现在发送一条消息:
点击之前创建好的应用:推送
点击发送通知:输入推送的内容
往下拉,选择目标的平台,立即发送
效果:
此时LogCat的显示为
先收到通知,然后走打开通知
/com.demo.jpdemo E/JPUSH---: onReceive:cn.jpush.android.intent.NOTIFICATION_RECEIVED
/com.demo.jpdemo E/JPUSH---: onReceive:通知的内容为:我是第一条推送,通知的标题为:JPDemo
/com.demo.jpdemo E/JPUSH---: onReceive:cn.jpush.android.intent.NOTIFICATION_OPENED
完成了。
实现更多的内容,请可以参考官方集成文档进行学习
https://docs.jiguang.cn/jpush/client/Android/android_guide/
更多的API参考: