摘要:產品為了提高推送送達率,提了一個需求在推送關閉的情況下顯示一個小,點擊跳轉到消息設置界面。第一步獲取推送狀態這里我主要參考極光推送。然后我們在側做一些兼容處理跳轉到消息設置頁面需要跳轉時,我們直接用這個函數就行了。
產品為了提高推送送達率,提了一個需求:在 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() 這個函數就行了。
上面就是開發中遇到的兩個難點,如果此篇文章你認為對你有用,可以點個贊表示對我的鼓勵,謝謝。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109355.html
摘要:產品為了提高推送送達率,提了一個需求在推送關閉的情況下顯示一個小,點擊跳轉到消息設置界面。第一步獲取推送狀態這里我主要參考極光推送。然后我們在側做一些兼容處理跳轉到消息設置頁面需要跳轉時,我們直接用這個函數就行了。 產品為了提高推送送達率,提了一個需求:在 APP 推送關閉的情況下顯示一個小 TIP,點擊 TIP 跳轉到 APP 消息設置界面。 我們的 APP 是基于 React N...
摘要:前言這周完成了公司更新非熱更新功能,在這里總結一下。即需要更新的代碼和資源時,需要有這個更新的功能。這樣的話,用戶可以通過進入的下載頁,來進行的更新。具體代碼實現用到了中的。 前言 這周完成了公司 React Native app 更新(非熱更新)功能,在這里總結一下。 1.首先,提出一個問題 我們的 app(基于RN)已經有 熱更新 功能了,為什么還要一個更新的功能? 因為熱更新只會...
閱讀 2027·2023-04-26 01:33
閱讀 1659·2023-04-26 00:52
閱讀 1035·2021-11-18 13:14
閱讀 5393·2021-09-26 10:18
閱讀 2901·2021-09-22 15:52
閱讀 1488·2019-08-29 17:15
閱讀 3016·2019-08-29 16:11
閱讀 1038·2019-08-29 16:11