摘要:产品为了提高推送送达率,提了一个需求在推送关闭的情况下显示一个小,点击跳转到消息设置界面。第一步获取推送状态这里我主要参考极光推送。然后我们在侧做一些兼容处理跳转到消息设置页面需要跳转时,我们直接用这个函数就行了。
产品为了提高推送送达率,提了一个需求:在 APP 推送关闭的情况下显示一个小 TIP,点击 TIP 跳转到 APP 消息设置界面。
我们的 APP 是基于 React Native 开发的,这些功能 Facebook 官方没有提供,需要我们开发对应的原生模块。
因为开发原生模块属于比较深入的内容了,写这篇文章时我就默认阅读者已经具有一定的 Objective-C 和 Java 开发能力,下面就直接贴代码说思路了。
开发一个原生模块的基础知识可以直接看官方文档,写的很详细,我这里就不多重复了。
React Native 开发 Android 原生模块
React Native 开发 iOS 原生模块
下面开始分析实现。
第一步:获取 APP 推送状态这里我主要参考极光推送。因为公司内部有统一的推送 SDK(主要整合了市面上多家推送服务公司和手机厂商的推送服务),一些极光推送很方便的功能暂时用不了,只能自己参考实现。
在我的实现里,获取 APP 推送状态主要做了两件事:
兼容多个系统版本(这部分都是极光推送开发者的功劳);
以 Promise 的形式进行封装(极光推送是基于 callback 的)
getSystemNoticeStatus() 这个函数,在 APP 推送开启的情况下返回 true,未开启情况返回 false。
iOS 代码如下:
参考链接:https://github.com/jpush/jpus...
RCT_EXPORT_METHOD( getSystemNoticeStatus: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject ) { dispatch_async( dispatch_get_main_queue(), ^{ float systemVersion = [[UIDevice currentDevice].systemVersion floatValue]; if ( systemVersion >= 8.0 ) { UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings]; UIUserNotificationType type = settings.types; if ( type == UIUserNotificationTypeNone ) { return(resolve (@NO) ); }else { return(resolve (@YES) ); } }else if ( systemVersion >= 10.0 ) { [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler: ^ (UNNotificationSettings * _Nonnull settings) { switch ( settings.authorizationStatus ) { case UNAuthorizationStatusDenied: case UNAuthorizationStatusNotDetermined: return(resolve (@NO) ); break; case UNAuthorizationStatusAuthorized: return(resolve (@YES) ); break; } }]; } } ); }
Android 代码如下:
参考链接:
https://github.com/jpush/jpus...
/** * 获取 APP 系统通知状态 * * */ @ReactMethod public void getSystemNoticeStatus(Promise promise) { promise.resolve(hasPermission("OP_POST_NOTIFICATION")); } private boolean hasPermission(String appOpsServiceId) { Context context = getReactApplicationContext(); if (Build.VERSION.SDK_INT >= 24) { NotificationManager mNotificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE); return mNotificationManager.areNotificationsEnabled(); }else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); ApplicationInfo appInfo = context.getApplicationInfo(); String pkg = context.getPackageName(); int uid = appInfo.uid; Class appOpsClazz; try { appOpsClazz = Class.forName(AppOpsManager.class.getName()); Method checkOpNoThrowMethod = appOpsClazz.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class); Field opValue = appOpsClazz.getDeclaredField(appOpsServiceId); int value = opValue.getInt(Integer.class); Object result = checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg); return Integer.parseInt(result.toString()) == AppOpsManager.MODE_ALLOWED; } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return false; }
然后我们在 JavaScript侧直接引用就可
import { Platform, NativeModules, } from "react-native"; function getSystemNoticeStatus() { NativeModules.appName.getSystemNoticeStatus().then((isOpen) => { console.log("getSystemNotice", isOpen) // }).catch((e) => { console.log("getSystemNoticeStatus error", e) }); }第二步:跳转到 APP 设置界面
跳转到 APP 设置界面也要考虑不同系统版本的兼容。比如说 iOS11+ 现在只允许跳转到系统设置首页/该应用的设置界面,Android 还要考虑不同厂商对 APP 设置页面的魔改,很是头疼。
首先 iOS 适配,我们直接跳转到该应用的设置首页,就是下图:
这个开发比较简单,直接在 React Native 中引用 Linking.openURL("app-settings:") 就行;
Android 就要多些一些代码了,具体的适配可以看注释:
/** * * 跳转到系统通知设置界面 * this.appContext 表示文件/应用的上下文环境 * */ @ReactMethod public void openSystemNoticeView(){ try { // 跳转到通知设置界面 Intent intent = new Intent(); intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS); //这种方案适用于 API 26, 即8.0(含8.0)以上可以用 intent.putExtra(EXTRA_APP_PACKAGE, this.appContext.getPackageName()); intent.putExtra(EXTRA_CHANNEL_ID, this.appContext.getApplicationInfo().uid); //这种方案适用于 API21——25,即 5.0——7.1 之间的版本可以使用 intent.putExtra("app_package", this.appContext.getPackageName()); intent.putExtra("app_uid", this.appContext.getApplicationInfo().uid); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.appContext.startActivity(intent); } catch (Exception e) { e.printStackTrace(); // 出现异常则跳转到应用设置界面:锤子 Intent intent = new Intent(); //下面这种方案是直接跳转到当前应用的设置界面。 //https://blog.csdn.net/ysy950803/article/details/71910806 intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", this.appContext.getPackageName(), null); intent.setData(uri); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.appContext.startActivity(intent); } }
然后我们在 JavaScript 侧做一些兼容处理:
import { Linking, Platform, } from "react-native"; /** * 跳转到 APP 消息设置页面 * */ export function openSystemNoticeSetting() { if (Platform.OS === "android") { NativeModules.appName.openSystemNoticeView(); } else { Linking.openURL("app-settings:") .catch(err => console.log("openSystemSetting error", err)); } }
需要跳转时,我们直接用openSystemNoticeSetting() 这个函数就行了。
上面就是开发中遇到的两个难点,如果此篇文章你认为对你有用,可以点个赞表示对我的鼓励,谢谢。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/74043.html
摘要:产品为了提高推送送达率,提了一个需求在推送关闭的情况下显示一个小,点击跳转到消息设置界面。第一步获取推送状态这里我主要参考极光推送。然后我们在侧做一些兼容处理跳转到消息设置页面需要跳转时,我们直接用这个函数就行了。 产品为了提高推送送达率,提了一个需求:在 APP 推送关闭的情况下显示一个小 TIP,点击 TIP 跳转到 APP 消息设置界面。 我们的 APP 是基于 React N...
摘要:前言这周完成了公司更新非热更新功能,在这里总结一下。即需要更新的代码和资源时,需要有这个更新的功能。这样的话,用户可以通过进入的下载页,来进行的更新。具体代码实现用到了中的。 前言 这周完成了公司 React Native app 更新(非热更新)功能,在这里总结一下。 1.首先,提出一个问题 我们的 app(基于RN)已经有 热更新 功能了,为什么还要一个更新的功能? 因为热更新只会...
阅读 1628·2021-11-02 14:42
阅读 525·2021-10-18 13:24
阅读 943·2021-10-12 10:12
阅读 1819·2021-09-02 15:41
阅读 3205·2019-08-30 15:56
阅读 2876·2019-08-29 16:09
阅读 2057·2019-08-29 11:13
阅读 3620·2019-08-28 18:06