기술 블로그
react-native android 14 정확한 알람 대응 본문
반응형
정확한 알람 예약은 기본적으로 거부됨
https://developer.android.com/about/versions/14/behavior-changes-all?hl=ko
안드로이드 14부터 정확한 알람 권한이 비활성화 되어 사용자로 부터 권한을 받아야 한다.
사내에서 운영 중인 어플리케이션은 rn 서드파티 라이브러리를 통해 권한을 요청하고 관리해왔지만
현 시점 대응한 라이브러리가 없어 직접 네이티브 모듈을 구축해야했다.
SCHEDULE_EXACT_ALARM은 선택적 권한이 아니기 때문에
알림상자로 권한 승인은 불가능하고 해당 앱의 설정으로 이동시켜주는것이 최선이다.
// android/app/src/main/AndroidManifest.xml
.
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
.
// android/app/src/main/java/com/integrateapp/AlarmPermissionModule.java
import android.app.AlarmManager;
import android.content.Context;
import android.os.Build;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
public class AlarmPermissionModule extends ReactContextBaseJavaModule {
public AlarmPermissionModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "AlarmPermissionModule";
}
// 알람을 묻습니다.
@ReactMethod
public void canScheduleExactAlarms(Promise promise) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AlarmManager alarmManager = (AlarmManager) getReactApplicationContext().getSystemService(Context.ALARM_SERVICE);
promise.resolve(alarmManager.canScheduleExactAlarms());
} else {
promise.resolve(true); // Older versions don't require this permission
}
}
// 설정창으로 이동합니다.
@ReactMethod
public void openAlarmSettings() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
intent.setData(Uri.parse("package:com.hackers.HackersOne"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null) {
getReactApplicationContext().startActivity(intent);
}
}
}
}
// android/app/src/main/java/com/이름/AlarmPermissionModule.java
package com.hackers.integrateapp;
import android.app.AlarmManager;
import android.content.Context;
import android.os.Build;
import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
public class AlarmPermissionModule extends ReactContextBaseJavaModule {
public AlarmPermissionModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "AlarmPermissionModule";
}
// 알람을 묻습니다.
@ReactMethod
public void canScheduleExactAlarms(Promise promise) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AlarmManager alarmManager = (AlarmManager) getReactApplicationContext().getSystemService(Context.ALARM_SERVICE);
promise.resolve(alarmManager.canScheduleExactAlarms());
} else {
promise.resolve(true); // Older versions don't require this permission
}
}
// 설정창으로 이동합니다.
@ReactMethod
public void openAlarmSettings() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);
intent.setData(Uri.parse("package:com.hackers.HackersOne"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null) {
getReactApplicationContext().startActivity(intent);
}
}
}
}
packages.add(new AlarmPermissionPackage());
// permission.ts
import {Alert, Platform, NativeModules, Linking} from 'react-native';
import * as Permissions from 'react-native-permissions';
import COMMON_STATES from '../../../../Constants/Common';
const {AlarmPermissionModule} = NativeModules;
const permissionScheduleExactAlarm = async () => {
if (Platform.OS === 'ios' || (Platform.Version as number) < 34) {
return true;
}
try {
// 권한 확인
const scheduleExactAlarmPermission = await AlarmPermissionModule.canScheduleExactAlarms();
console.log('permission ' + scheduleExactAlarmPermission);
if (scheduleExactAlarmPermission) {
return true;
}
return false;
} catch (e) {
throw new Error('permissionScheduleExactAlarm error');
}
};
const ScheduleExactAlarmSetting = () => {
AlarmPermissionModule.openAlarmSettings();
};
const addAlarmPermissionRequireAlert = () => {
Alert.alert(
'권한 등록',
'앱을 사용하기 위해\n접근 권한 허용이 필요합니다.',
[
{text: '권한설정', onPress: ScheduleExactAlarmSetting},
//
{text: '취소'},
],
{
cancelable: false,
},
);
};
//노티 권한 ( POST_NOTIFICATIONS)
const permissionNotification = async () => {
if (Platform.OS === 'ios' || (Platform.Version as number) < 33) {
return true;
}
const PERMISSION =
Platform.OS === 'android'
? Permissions.PERMISSIONS.ANDROID.POST_NOTIFICATIONS
: Permissions.PERMISSIONS.IOS.CAMERA;
try {
const notificationPermission = await Permissions.request(PERMISSION);
if (notificationPermission !== Permissions.RESULTS.GRANTED) {
return false;
}
return true;
} catch (e) {
throw new Error('permissionNotification error');
}
};
//노티 얼럿( POST_NOTIFICATIONS)
const addNotificationPermissionRequireAlert = () => {
Alert.alert(
'권한 등록',
'앱을 사용하기 위해\n접근 권한 허용이 필요합니다.',
[
{
text: '권한설정',
onPress: () =>
Linking.sendIntent('android.settings.APP_NOTIFICATION_SETTINGS', [
{
key: 'android.provider.extra.APP_PACKAGE',
value: COMMON_STATES.androidPackageName,
},
]),
},
//
{text: '취소'},
],
{
cancelable: false,
},
);
};
export {
permissionScheduleExactAlarm,
addNotificationPermissionRequireAlert,
permissionNotification,
addAlarmPermissionRequireAlert,
};
사용
const isPermissionCamera = await permissionNotification();
if (!isPermissionCamera) {
addNotificationPermissionRequireAlert();
return;
}
AOS 13 이상 POST_NOTIFICATIONS 대응
- 안드로이드 13,14버전에서 앱을 신규 설치 시 notification 설정이 기본적으로 꺼져있다. 안드로이드 12 버전에서는 notification이 설치 이후 기본적으로 켜져있고
기기를 안드로이드 13 이상으로 업그레이드할 때 모든 대상 앱에 권한을 자동으로 사전 부여하는 것으로 보이나
안드로이드 13, 14에 앱을 신규 설치 시 notification이 꺼져있음을 에뮬레이터에서 확인된다.
위와 같은 이유로 해당 권한을 추가하는 부분도 구현되어 있다.
반응형
'프론트엔드' 카테고리의 다른 글
javascript 코테를 위한 도구들 (0) | 2024.10.30 |
---|---|
프론트엔드에서의 경로 유지 멀티파일 전송과 성능 비교에 관하여 (0) | 2024.08.26 |
js 입출력 (0) | 2023.11.16 |
[TIL] 에러코드 (0) | 2023.10.20 |
[TIL] 웹 브라우저 이해 (0) | 2023.10.17 |
Comments