feat(MOB): 앱 설치 권한 없을 시 설정 화면 자동 안내
- installApk에 canRequestPackageInstalls() 권한 체크 추가 - 권한 없으면 안내 다이얼로그 → 설정 화면으로 이동 - onActivityResult로 설정 복귀 후 자동 설치 재시도 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,11 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
@@ -33,6 +35,7 @@ public class AppUpdateChecker {
|
||||
|
||||
private final Activity activity;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
private String pendingInstallFileName;
|
||||
|
||||
public AppUpdateChecker(Activity activity) {
|
||||
this.activity = activity;
|
||||
@@ -178,9 +181,81 @@ public class AppUpdateChecker {
|
||||
}
|
||||
|
||||
/**
|
||||
* APK 설치 Intent 실행
|
||||
* APK 설치 Intent 실행 (권한 체크 포함)
|
||||
*/
|
||||
private void installApk(String fileName) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!activity.getPackageManager().canRequestPackageInstalls()) {
|
||||
// 권한 없음 → 설정 화면 안내
|
||||
pendingInstallFileName = fileName;
|
||||
activity.runOnUiThread(() -> showInstallPermissionDialog());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
launchInstallIntent(fileName);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Install APK error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 출처를 알 수 없는 앱 설치 권한 안내 다이얼로그
|
||||
*/
|
||||
private void showInstallPermissionDialog() {
|
||||
if (activity.isFinishing() || activity.isDestroyed()) return;
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle("설치 권한 필요")
|
||||
.setMessage("앱 업데이트를 설치하려면 '출처를 알 수 없는 앱 설치' 권한을 허용해주세요.\n\n설정 화면으로 이동합니다.")
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("설정으로 이동", (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
openInstallPermissionSettings();
|
||||
})
|
||||
.setNegativeButton("취소", (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
pendingInstallFileName = null;
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 출처를 알 수 없는 앱 설치 설정 화면 열기
|
||||
*/
|
||||
private void openInstallPermissionSettings() {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
|
||||
intent.setData(Uri.parse("package:" + activity.getPackageName()));
|
||||
activity.startActivityForResult(intent, 1001);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Open install permission settings error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 설정 화면에서 돌아온 후 설치 재시도
|
||||
*/
|
||||
public void onActivityResult(int requestCode, int resultCode) {
|
||||
if (requestCode == 1001 && pendingInstallFileName != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& activity.getPackageManager().canRequestPackageInstalls()) {
|
||||
launchInstallIntent(pendingInstallFileName);
|
||||
} else {
|
||||
Log.w(TAG, "Install permission still not granted");
|
||||
}
|
||||
pendingInstallFileName = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 실제 APK 설치 Intent 실행
|
||||
*/
|
||||
private void launchInstallIntent(String fileName) {
|
||||
try {
|
||||
File apkFile = new File(activity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName);
|
||||
if (!apkFile.exists()) {
|
||||
@@ -202,7 +277,7 @@ public class AppUpdateChecker {
|
||||
activity.startActivity(installIntent);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Install APK error", e);
|
||||
Log.e(TAG, "Launch install intent error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,15 @@ import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
|
||||
public class MainActivity extends BridgeActivity {
|
||||
|
||||
private AppUpdateChecker updateChecker;
|
||||
|
||||
// 채널 ID (FCM payload의 android.notification.channel_id 로 사용할 값)
|
||||
public static final String CHANNEL_DEFAULT = "push_default";
|
||||
public static final String CHANNEL_VENDOR_REGISTER = "push_vendor_register";
|
||||
@@ -27,7 +30,8 @@ public class MainActivity extends BridgeActivity {
|
||||
createNotificationChannels();
|
||||
|
||||
// 인앱 업데이트 체크
|
||||
new AppUpdateChecker(this).checkForUpdate();
|
||||
updateChecker = new AppUpdateChecker(this);
|
||||
updateChecker.checkForUpdate();
|
||||
|
||||
// WebView 줌 설정 (핀치 줌 활성화)
|
||||
getBridge().getWebView().getSettings().setSupportZoom(true);
|
||||
@@ -137,4 +141,12 @@ public class MainActivity extends BridgeActivity {
|
||||
nm.createNotificationChannel(chPurchaseOrder);
|
||||
nm.createNotificationChannel(chContract);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (updateChecker != null) {
|
||||
updateChecker.onActivityResult(requestCode, resultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user