├── .gitignore ├── README.md ├── app ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── avos │ │ └── avoscloud │ │ └── PushDemo │ │ ├── CustomReceiver.java │ │ ├── PushDemo.java │ │ └── PushDemoApp.java │ └── res │ ├── drawable │ ├── blue_btn.xml │ ├── blue_btn_normal.xml │ ├── blue_btn_pressed.xml │ └── notification.png │ ├── layout │ ├── callback1.xml │ ├── callback2.xml │ └── main.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # Windows thumbnail db 40 | Thumbs.db 41 | 42 | # OSX files 43 | .DS_Store 44 | 45 | # Android Studio 46 | *.iml 47 | .idea 48 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 49 | .gradle 50 | build/ 51 | .navigation 52 | captures/ 53 | output.json 54 | 55 | # NDK 56 | obj/ 57 | .externalNativeBuild 58 | 59 | # Keystore files 60 | # Uncomment the following lines if you do not want to check your keystore files in. 61 | #*.jks 62 | #*.keystore 63 | 64 | # External native build folder generated in Android Studio 2.2 and later 65 | .externalNativeBuild 66 | .cxx/ 67 | 68 | # Google Services (e.g. APIs or Firebase) 69 | # google-services.json 70 | 71 | # Freeline 72 | freeline.py 73 | freeline/ 74 | freeline_project_description.json 75 | 76 | # fastlane 77 | fastlane/report.xml 78 | fastlane/Preview.html 79 | fastlane/screenshots 80 | fastlane/test_output 81 | fastlane/readme.md 82 | 83 | # Version control 84 | vcs.xml 85 | 86 | # lint 87 | lint/intermediates/ 88 | lint/generated/ 89 | lint/outputs/ 90 | lint/tmp/ 91 | # lint/reports/ 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 介绍 2 | 3 | 一个 LeanCloud 推送消息的简单 Demo,直接在客户端推送消息,并自己接收。 4 | 5 | ![img](https://raw.githubusercontent.com/lzwjava/plan/master/push.png) 6 | 7 | 8 | **实际生产环境中,建议从应用设置里关闭从客户端推送,并且使用我们提供的推送 web 平台或者 REST API 发起服务端推送更为合适。否则推送可能被滥用。** 9 | 10 | 你可以从推送 Demo 中学到: 11 | 12 | * 如何自定义接受推送信息的 `Receiver` 13 | * 如何订阅频道 14 | * 如何保存 installation 15 | * 如何根据 `installationId` 或 `channel` 推送,随意定义你的推送对象 16 | * 如何推送 `json` 数据以及获取数据 17 | * 如何从客户端发起推送 18 | 19 | ## 替换 App 信息 20 | 21 | Demo 使用的是公共的 AppId、AppKey 和 ServerUrl,您可以在`com.avos.avoscloud.PushDemo.PushDemoApp`修改成您自己的应用 AppId、AppKey 和 ServerUrl。 22 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | defaultConfig { 6 | applicationId "com.avos.avoscloud.PushDemo" 7 | minSdkVersion 26 8 | targetSdkVersion 29 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | compileOptions { 14 | sourceCompatibility JavaVersion.VERSION_1_8 15 | targetCompatibility JavaVersion.VERSION_1_8 16 | } 17 | } 18 | 19 | dependencies { 20 | implementation fileTree(dir: 'libs', include: ['*.jar']) 21 | implementation 'androidx.appcompat:appcompat:1.3.0' 22 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 23 | implementation 'com.google.android.material:material:1.3.0' 24 | testImplementation 'junit:junit:4.13.2' 25 | androidTestImplementation 'androidx.test:runner:1.3.0' 26 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 27 | 28 | implementation 'cn.leancloud:storage-android:8.2.0' 29 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' 30 | implementation 'cn.leancloud:realtime-android:8.2.0' 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/avos/avoscloud/PushDemo/CustomReceiver.java: -------------------------------------------------------------------------------- 1 | package com.avos.avoscloud.PushDemo; 2 | import android.content.BroadcastReceiver; 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | public class CustomReceiver extends BroadcastReceiver { 7 | @Override 8 | public void onReceive(Context context, Intent intent) { 9 | // 获取推送消息数据 10 | String message = intent.getStringExtra("com.avoscloud.Data"); 11 | String channel = intent.getStringExtra("com.avoscloud.Channel"); 12 | System.out.println("message=" + message + ", channel=" + channel); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/avos/avoscloud/PushDemo/PushDemo.java: -------------------------------------------------------------------------------- 1 | package com.avos.avoscloud.PushDemo; 2 | import androidx.appcompat.app.AppCompatActivity; 3 | 4 | import android.app.Activity; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import cn.leancloud.LCException; 14 | import cn.leancloud.LCInstallation; 15 | import cn.leancloud.LCPush; 16 | import cn.leancloud.LCQuery; 17 | import cn.leancloud.json.JSONObject; 18 | import io.reactivex.Observer; 19 | import io.reactivex.disposables.Disposable; 20 | 21 | 22 | public class PushDemo extends AppCompatActivity { 23 | /** 24 | * Called when the activity is first created. 25 | */ 26 | @Override 27 | public void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.main); 30 | final String installationId = LCInstallation.getCurrentInstallation().getInstallationId(); 31 | 32 | final TextView t = (TextView) this.findViewById(R.id.mylabel); 33 | // 显示的设备的 installationId,用于推送的设备标示 34 | t.setText("这个设备的 id: " + installationId); 35 | 36 | final EditText channelEdit = (EditText) this.findViewById(R.id.channel); 37 | final EditText msgEdit = (EditText) this.findViewById(R.id.message); 38 | final Button customPushtn = (Button) this.findViewById(R.id.customPush); 39 | customPushtn.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | LCQuery pushQuery = LCInstallation.getQuery(); 43 | pushQuery.whereEqualTo("channels", channelEdit.getText().toString()); 44 | LCPush push = new LCPush(); 45 | push.setQuery(pushQuery); 46 | push.setMessage(msgEdit.getText().toString()); 47 | push.setPushToAndroid(true); 48 | push.sendInBackground().subscribe(new Observer() { 49 | @Override 50 | public void onSubscribe(Disposable d) { 51 | } 52 | @Override 53 | public void onNext(JSONObject jsonObject) { 54 | System.out.println("推送成功" + jsonObject); 55 | } 56 | @Override 57 | public void onError(Throwable throwable) { 58 | System.out.println("推送失败,错误信息:" + throwable.getMessage()); 59 | } 60 | @Override 61 | public void onComplete() { 62 | } 63 | }); 64 | 65 | } 66 | }); 67 | final Button pushButton = (Button) this.findViewById(R.id.pushBtn); 68 | pushButton.setOnClickListener(new View.OnClickListener() { 69 | @Override 70 | public void onClick(View v) { 71 | System.out.println("installationId:" + installationId); 72 | 73 | LCQuery pushQuery = LCInstallation.getQuery(); 74 | pushQuery.whereEqualTo("installationId", installationId); 75 | LCPush push = new LCPush(); 76 | push.setPushToAndroid(true); 77 | push.sendMessageInBackground(msgEdit.getText().toString(),pushQuery).subscribe(new Observer() { 78 | @Override 79 | public void onSubscribe(Disposable d) { 80 | } 81 | @Override 82 | public void onNext(Object object) { 83 | System.out.println("推送成功" + object); 84 | } 85 | @Override 86 | public void onError(Throwable throwable) { 87 | LCException exception = new LCException(throwable); 88 | System.out.println("推送失败,错误信息:" + exception.getCode() +exception.getMessage()); 89 | } 90 | @Override 91 | public void onComplete() { 92 | } 93 | }); 94 | } 95 | }); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/avos/avoscloud/PushDemo/PushDemoApp.java: -------------------------------------------------------------------------------- 1 | package com.avos.avoscloud.PushDemo; 2 | 3 | import android.app.Application; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | 7 | import cn.leancloud.LCInstallation; 8 | import cn.leancloud.LCLogger; 9 | import cn.leancloud.LCObject; 10 | import cn.leancloud.LeanCloud; 11 | import cn.leancloud.push.PushService; 12 | import io.reactivex.Observer; 13 | import io.reactivex.disposables.Disposable; 14 | 15 | public class PushDemoApp extends Application { 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | //开启调试日志 21 | LeanCloud.setLogLevel(LCLogger.Level.DEBUG); 22 | // 初始化应用信息 23 | LeanCloud.initialize(this,"Gvv2k8PugDTmYOCfuK8tiWd8-gzGzoHsz", "dpwAo94n81jPsHVxaWwdxJVu", "https://gvv2k8pu.lc-cn-n1-shared.com"); 24 | // 设置默认打开的 Activity 25 | PushService.setDefaultPushCallback(this, PushDemo.class); 26 | // 订阅频道,当该频道消息到来的时候,打开对应的 Activity 27 | // 参数依次为:当前的 context、频道名称、回调对象的类 28 | PushService.subscribe(this, "public", PushDemo.class); 29 | PushService.subscribe(this, "private", PushDemo.class); 30 | PushService.subscribe(this, "protected", PushDemo.class); 31 | 32 | // 设置通知展示的默认 channel 33 | NotificationChannel channel = new NotificationChannel("channelid01", "channelid01", NotificationManager.IMPORTANCE_DEFAULT); 34 | channel.setDescription("用于 Demo 测试的 channel"); 35 | NotificationManager notificationManager = getSystemService(NotificationManager.class); 36 | notificationManager.createNotificationChannel(channel); 37 | PushService.setDefaultChannelId(this, channel.getId()); 38 | 39 | 40 | // 保存 Installation 41 | LCInstallation.getCurrentInstallation().saveInBackground().subscribe(new Observer() { 42 | @Override 43 | public void onSubscribe(Disposable d) { 44 | } 45 | 46 | @Override 47 | public void onNext(LCObject avObject) { 48 | // 关联 installationId 到用户表等操作。 49 | String installationId = LCInstallation.getCurrentInstallation().getInstallationId(); 50 | System.out.println("保存成功:" + installationId); 51 | } 52 | 53 | @Override 54 | public void onError(Throwable e) { 55 | System.out.println("保存失败,错误信息:" + e.getMessage()); 56 | } 57 | 58 | @Override 59 | public void onComplete() { 60 | } 61 | }); 62 | 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_btn_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_btn_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leancloud/android-push-demo/cc469dde2ea57cc5c5c337d81b0e6bae97d13833/app/src/main/res/drawable/notification.png -------------------------------------------------------------------------------- /app/src/main/res/layout/callback1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/callback2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 19 | 20 | 25 | 26 | 31 | 32 | 33 | 36 | 37 | 42 | 43 | 48 | 49 | 50 | 51 | 56 | 57 |