安卓SDK——极光推送

关于安卓推送常见的解决方案

之前看见了一篇老文章很好,就顺手转了

https://blog.****.net/nishigesb123/article/details/90255770

回过头发现和看的视频讲的内容基本一样呢,233

安卓SDK——极光推送

本文选择了“使用第三方平台”这一解决方案,所选择的平台为——极光推送

推送平台好像挺多的,说起来,现在的推送平台业务拓展的挺多,像数据统计分析、社会化分享基本都有在做,选择一个靠谱的就固定下来都用它家的感觉会好很多,就不用来回注册了← ←


极光推送(JPush)

概述

官网:https://www.jiguang.cn/

推送部分官网:https://www.jiguang.cn/push

推送部分开发文档:https://docs.jiguang.cn/jpush/guideline/intro/

安卓集成指南:https://docs.jiguang.cn/jpush/client/Android/android_guide/

简介

JPush 是经过考验的大规模 App 推送平台,每天推送消息数超过 5 亿条。 开发者集成 SDK 后,可以通过调用 API 推送消息。同时,JPush 提供可视化的 web 端控制台发送通知,统计分析推送效果。 JPush 全面支持 Android, iOS, Winphone 三大手机平台。

消息形式

JPush 提供四种消息形式:通知,自定义消息,富媒体和本地通知。

通知

或者说 Push Notification,即指在手机的通知栏(状态栏)上会显示的一条通知信息。 通知主要用来达到提示用户的目的,应用于新闻内容、促销活动、产品信息、版本更新提醒、订单状态提醒等多种场景

开发者参考文档:Push API v3 notification

自定义消息

自定义消息不是通知,所以不会被 SDK 展示到通知栏上。其内容完全由开发者自己定义。 自定义消息主要用于应用的内部业务逻辑。一条自定义消息推送过来,有可能没有任何界面显示。

开发者参考文档:Push API v3 message

富媒体

JPush 支持开发者发送图文并茂的通知,从而更好的传达信息,带来更丰富的用户互动。 JPush 提供了 5 种模板,开发者可以通过填充模板的内容,发送 landing page、弹窗、信息流形式的富媒体通知。 开发者还可以直接通过 URL 发送预先编辑好的页面。 富媒体当前支持 Android 平台,为更好的使用富媒体的功能,建议更新当前 SDK 版本至 v2.1.8 及以上。 暂时只能通过极光推送的控制台发送,不支持 API 形式。

Android 开发者参考文档:Rich Push 开发指南

本地通知

本地通知 API 不依赖于网络,无网条件下依旧可以触发;本地通知的定时时间是自发送时算起的,不受中间关机等操作的影响。 本地通知与网络推送的通知是相互独立的,不受保留最近通知条数上限的限制。 本地通知适用于在特定时间发出的通知,如一些 Todo 和闹钟类的应用,在每周、每月固定时间提醒用户回到应用查看任务。

Android 开发者参考文档:Android 本地通知 iOS 开发者参考文档:iOS 本地通知

 集成与创建

当然首先得注册和创建app拿到对应的key

创建app的入口:https://www.jiguang.cn/dev/#/app/create

集成分手动集成和自动集成。

可以参考:https://docs.jiguang.cn/jpush/client/Android/android_guide/文档部分的教程

快速集成Demo

也可以考虑使用图示中提供的快速集成服务,下载Demo进行修改

安卓SDK——极光推送

使用快速集成Demo这部分的教程可以参考:https://docs.jiguang.cn/jpush/client/Android/android_3m/

首先需要 import module 导入 下载的Demo(要解压..)

安卓SDK——极光推送

然后老样子,看看有什么错误提示,按提示进行修改即可,基本就是这种的,删几句话,改几个词就好

安卓SDK——极光推送

比较值得一提的是,如果使用的As版本较新,会有如下提示

安卓SDK——极光推送

ERROR: The SourceSet 'instrumentTest' is not recognized by the Android Gradle Plugin. Perhaps you misspelled something?
Affected Modules: JPushExample(1319516)

 

全文大意就是缺少instrumentTest,问题的根源是在新版本gradle中已经弃置了instrumentTest,改成androidTest即可

不过其实查一下也查得到

效果预览

差不多改完就能运行了,不过竟然提示版本太低,Demo都不与时俱进的吗(好感-1)

安卓SDK——极光推送安卓SDK——极光推送

然后在后台就可以进行推送测试了~

 安卓SDK——极光推送

通知分三种,通知、自定义消息、富媒体消息,以发送通知为

安卓SDK——极光推送

下面可以进行一些简单的配置

安卓SDK——极光推送

点击发送可以看到效果如下,然后就可以在模拟器(手机)的通知栏上看到相关推送内容了

安卓SDK——极光推送

通知是可以点开的

安卓SDK——极光推送

自定义消息的效果如下,可能看不是很清楚,在高级功能按钮上面一点点的文本框内出现了对应的内容,这个demo屏幕适配不是很好,界面拖不动233

安卓SDK——极光推送

最后一个是富媒体消息

可以支持模板(算是弹窗广告吗233)和URL两种

安卓SDK——极光推送

乍一看和普通的通知没啥区别

安卓SDK——极光推送

点开来就不一样了,像极了国产页游的垃圾广告(误)

安卓SDK——极光推送


案例

假设已经完成了SDK的集成,推荐使用自动集成的方式,只需要简单的配一下Gradle即可,具体可以参考上面给出的文档链接。

本文选择了自动集成的方案,手动集成可以参考文档,一步一步来。

权限

必要的一些权限(实际上一两个会提示非系统应用无法获得,但是不影响)

WAKE_LOCK和VIBRATE为可选权限,注意第一条权限的前缀需要改为自己对应的包名

    <!-- Required  一些系统要求的权限,如访问网络等-->
    <uses-permission android:name="com.example.a5_20jpush.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" />

初始化

推荐创建一个类继承application来初始化,并在配置清单文件进行声明

package com.example.jpush;

import android.app.Application;

import cn.jpush.android.api.JPushInterface;

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        JPushInterface.setDebugMode(true);
        JPushInterface.init(this);
    }
}

安卓SDK——极光推送

广播接收器

这个不难理解,反正肯定是要一个的233。

代码可以直接复制Demo的稍微改一下(只是为了跑通 233,具体还是看需求),也可以参考下面的API

https://docs.jiguang.cn/jpush/client/Android/android_api/

package com.example.jpush;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Iterator;

import cn.jpush.android.api.JPushInterface;


/**
 * 自定义接收器
 *
 * 如果不定义这个 Receiver,则:
 * 1) 默认用户会打开主界面
 * 2) 接收不到自定义消息
 */
public class MyReceiver extends BroadcastReceiver {
	private static final String TAG = "JIGUANG-Example";

	@Override
	public void onReceive(Context context, Intent intent) {
		try {
			Bundle bundle = intent.getExtras();
			Log.d(TAG, "[MyReceiver] onReceive - " + intent.getAction() + ", extras: " + printBundle(bundle));

			if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
				String regId = bundle.getString(JPushInterface.EXTRA_REGISTRATION_ID);
				Log.d(TAG, "[MyReceiver] 接收Registration Id : " + regId);
				//send the Registration Id to your server...

			} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
				Log.d(TAG, "[MyReceiver] 接收到推送下来的自定义消息: " + bundle.getString(JPushInterface.EXTRA_MESSAGE));
				//processCustomMessage(context, bundle);

			} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
				Log.d(TAG, "[MyReceiver] 接收到推送下来的通知");
				int notifactionId = bundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);
				Log.d(TAG, "[MyReceiver] 接收到推送下来的通知的ID: " + notifactionId);

			} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
				Log.d(TAG, "[MyReceiver] 用户点击打开了通知");
				Toast.makeText(context,"用户点击打开了通知",Toast.LENGTH_SHORT).show();

				//打开自定义的Activity
				//Intent i = new Intent(context, TestActivity.class);
				//i.putExtras(bundle);
				//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP );
				//context.startActivity(i);

			} else if (JPushInterface.ACTION_RICHPUSH_CALLBACK.equals(intent.getAction())) {
				Log.d(TAG, "[MyReceiver] 用户收到到RICH PUSH CALLBACK: " + bundle.getString(JPushInterface.EXTRA_EXTRA));
				//在这里根据 JPushInterface.EXTRA_EXTRA 的内容处理代码,比如打开新的Activity, 打开一个网页等..

			} else if(JPushInterface.ACTION_CONNECTION_CHANGE.equals(intent.getAction())) {
				boolean connected = intent.getBooleanExtra(JPushInterface.EXTRA_CONNECTION_CHANGE, false);
				Log.w(TAG, "[MyReceiver]" + intent.getAction() +" connected state change to "+connected);
			} else {
				Log.d(TAG, "[MyReceiver] Unhandled intent - " + intent.getAction());
			}
		} catch (Exception e){

		}

	}

	// 打印所有的 intent extra 数据
	private static String printBundle(Bundle bundle) {
		StringBuilder sb = new StringBuilder();
		for (String key : bundle.keySet()) {
			if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
				sb.append("\nkey:" + key + ", value:" + bundle.getInt(key));
			}else if(key.equals(JPushInterface.EXTRA_CONNECTION_CHANGE)){
				sb.append("\nkey:" + key + ", value:" + bundle.getBoolean(key));
			} else if (key.equals(JPushInterface.EXTRA_EXTRA)) {
				if (TextUtils.isEmpty(bundle.getString(JPushInterface.EXTRA_EXTRA))) {
					Log.i(TAG, "This message has no Extra data");
					continue;
				}

				try {
					JSONObject json = new JSONObject(bundle.getString(JPushInterface.EXTRA_EXTRA));
					Iterator<String> it =  json.keys();

					while (it.hasNext()) {
						String myKey = it.next();
						sb.append("\nkey:" + key + ", value: [" +
								myKey + " - " +json.optString(myKey) + "]");
					}
				} catch (JSONException e) {
					Log.e(TAG, "Get message extra JSON error!");
				}

			} else {
				sb.append("\nkey:" + key + ", value:" + bundle.get(key));
			}
		}
		return sb.toString();
	}

/*	//send msg to MainActivity
	private void processCustomMessage(Context context, Bundle bundle) {
		if (MainActivity.isForeground) {
			String message = bundle.getString(JPushInterface.EXTRA_MESSAGE);
			String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
			Intent msgIntent = new Intent(MainActivity.MESSAGE_RECEIVED_ACTION);
			msgIntent.putExtra(MainActivity.KEY_MESSAGE, message);
			if (!ExampleUtil.isEmpty(extras)) {
				try {
					JSONObject extraJson = new JSONObject(extras);
					if (extraJson.length() > 0) {
						msgIntent.putExtra(MainActivity.KEY_EXTRAS, extras);
					}
				} catch (JSONException e) {

				}

			}
			LocalBroadcastManager.getInstance(context).sendBroadcast(msgIntent);
		}
	}*/
}

需要在配置清单声明

        <receiver
            android:name="com.example.jpush.MyReceiver"
            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="com.example.jpush" />
            </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>

安卓SDK——极光推送 

服务

一般来说是不用的?但是新版本似乎强制要求一个,内容啥都不写就好

package com.example.jpush;


import cn.jpush.android.service.JCommonService;

public class MyService extends JCommonService {
    public MyService() {
    }

}

安卓SDK——极光推送 

测试成功

安卓SDK——极光推送

安卓SDK——极光推送

设置别名

具体可以参考,似乎好像还提示TagAliasCallback过时的样子...

https://docs.jiguang.cn/jpush/client/Android/android_senior/#_1

在初始化的时候添加如下代码

        JPushInterface.setAlias(this, "YourAlias", new TagAliasCallback() {
            @Override
            public void gotResult(int i, String s, Set<String> set) {
                
            }
        });
        Set<String> tags = new HashSet<>();
        tags.add("test");
        JPushInterface.setTags(this, tags, new TagAliasCallback() {
            @Override
            public void gotResult(int i, String s, Set<String> set) {

            }
        });
    }