1、概述
- 用权限请求,被拒绝后无法再次请求
- 因此,思路为,检测权限状态,通过跳转设置界面,引导用户打开权限设置。
- 引入 react-native-permissions 库,调用 checkNotifications 检查通知权限的状态
- 跳转通知权限设置:
- ios:Linking.openURL(‘app-settings://notification/myapp’)
- Android设备上,使用 Linking.openSettings() 会打开当前设备的设置页面,而不是直接跳转到通知权限设置页面。要实现直接跳转到通知权限设置页面,可以使用原生Android代码。
2、Android 跳转通知权限设置
- 在项目中新建 OpenSettingsModule.java
package com.houseasst.app.prod.openSettings;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class OpenSettingsModule extends ReactContextBaseJavaModule {
@Override
public String getName() {
/**
* return the string name of the NativeModule which represents this class in JavaScript
* In JS access this module through React.NativeModules.OpenSettings
*/
return "OpenSettings";
}
@ReactMethod
public void openNotificationSettings(Callback cb) {
Activity currentActivity = getCurrentActivity();
Context context = getReactApplicationContext();
Intent intent = new Intent();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
} else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
} else {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + context.getPackageName()));
}
currentActivity.startActivity(intent);
}
/* constructor */
public OpenSettingsModule(ReactApplicationContext reactContext) {
super(reactContext);
}
}
- 在项目中新建 OpenSettingsPackage.java
package com.houseasst.app.prod.openSettings;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class OpenSettingsPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new OpenSettingsModule(reactContext));
return modules;
}
// @Override
// public List<<Class>? extends JavaScriptModule> createJSModules() {
// return Collections.emptyList();
// }
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
- MainApplication.java 中引入
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(
new OpenSettingsPackage()
);
return packages;
}
3、优化 Android 跳转设置界面后, Activity 销毁问题
在 Android 平台上使用 react-native-open-settings 或者 Linking 模块跳转到通知设置界面时,可能会出现应用程序自动重启的问题。这种问题通常是由于 Android 平台的特定行为导致的。
在 Android 平台上,如果应用程序进入后台,系统可能会强制关闭或销毁该应用程序的进程,以释放系统资源。使用 react-native-open-settings 或者 Linking 模块打开设备设置界面并返回应用程序时,Android 系统可能会认为应用程序已经进入了后台,然后强制关闭或销毁该进程,导致应用程序自动重启。
可以尝试在应用程序中添加以下代码,以防止应用程序在进入后台时被强制销毁:
public class MainActivity extends ReactActivity {
// ...
@Override
protected void onPause() {
super.onPause();
// 判断应用程序是否进入后台,如果是,则取消 Activity 的销毁
if (isAppInBackground()) {
moveTaskToBack(false);
}
}
// 判断应用程序是否进入后台
private boolean isAppInBackground() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
return !componentInfo.getPackageName().equals(getPackageName());
}
}
在应用程序进入后台时检测是否需要取消 Activity 的销毁,以避免应用程序在返回时被强制重启。同时,也可以尝试在 AndroidManifest.xml 文件中添加以下代码:
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
</activity>
这段代码会将 Activity 的 launchMode 设置为 singleTask,这样应用程序就不会在进入后台时被销毁。