In order to improve the rate of push delivery, the product proposed a requirement: when APP push is closed, a small TIP will be displayed. Click TIP to jump to the APP message setting interface.
Our APP is developed based on React Native. These functions are not officially provided by Facebook, so we need to develop corresponding Native modules.
Since developing native modules is a bit more in-depth, I’m writing this article with the assumption that the reader already has some Objective-C and Java development skills.
The basics of developing a native module can be seen directly in the official documentation, which is very detailed and I won’t repeat it here.
React Native develops Android Native modules
React Native develops iOS Native modules
Let’s start analyzing the implementation.
Step 1: Get APP push status
My main reference here is the aurora push. Because the company has a unified push SDK (mainly integrating the push services of many push service companies and mobile phone manufacturers in the market), some convenient functions of aurora push cannot be used for the time being, so we have to refer to and implement them by ourselves.
- Compatible with multiple system versions (partly thanks to aurora Push developers);
- In order to
Promise
The form of encapsulation (aurora push is based oncallback
)
GetSystemNoticeStatus () returns true if the APP push is on, false if it is not.
The iOS code is as follows:
Reference link: github.com/jpush/jpush…
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; } }]; }}); }Copy the code
The Android code is as follows:
Reference links:
Github.com/jpush/jpush…
/** * Get APP system notification status ** */
@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;
}
Copy the code
And then we can reference it directly on the JavaScript side
import {
Platform,
NativeModules,
} from 'react-native';
function getSystemNoticeStatus() {
NativeModules.appName.getSystemNoticeStatus().then((isOpen) = > {
console.log('getSystemNotice', isOpen) //
}).catch((e) = > {
console.log('getSystemNoticeStatus error', e)
});
}
Copy the code
Step 2: Jump to the APP Settings interface
Jumping to APP setting interface should also consider the compatibility of different system versions. For example, iOS11+ now only allows to jump to the system Settings home page/the application Settings interface, Android also consider different manufacturers of APP Settings page magic change, is a headache.
First of all, iOS adaptation, we directly jump to the app Settings home page, as shown below:
Linking. OpenURL (‘app-settings:’);
Android is going to have some more code, see the notes for specific adaptation:
/** ** Jump to system notification Settings * this.appContext indicates the context of the file/application ** /
@ReactMethod
public void openSystemNoticeView(a){
try {
// Go to the notification setting interface
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
// This solution applies to API 26, i.e. 8.0 and above
intent.putExtra(EXTRA_APP_PACKAGE, this.appContext.getPackageName());
intent.putExtra(EXTRA_CHANNEL_ID, this.appContext.getApplicationInfo().uid);
This scheme applies to API21 -- 25, that is, versions 5.0 -- 7.1 can be used
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();
// If there is an exception, go to the application setting interface: hammer
Intent intent = new Intent();
// Jump directly to the Settings screen of the current application.
//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); }}Copy the code
Then we do some compatibility on the JavaScript side:
import {
Linking,
Platform,
} from 'react-native';
/** * Jump to APP message setting page ** /
export function openSystemNoticeSetting() {
if (Platform.OS === "android") {
NativeModules.appName.openSystemNoticeView();
} else {
Linking.openURL('app-settings:')
.catch(err= > console.log('openSystemSetting error', err)); }}Copy the code
The above are the two difficulties encountered in the development, if you think this article is useful to you, you can click a “like” to express my encouragement, thank you.
Finally, I would like to recommend my personal official account “Lu Egg Lab”. I usually share some front-end technology and data analysis content. If you are interested, you can pay attention to the following: