Notice
Recent Posts
Recent Comments
Link
투케이2K
671. (Android/Java) application vnd.android.package-archive 사용해 외부 저장소에 저장된 apk 파일 자동 업데이트 수행 본문
Android
671. (Android/Java) application vnd.android.package-archive 사용해 외부 저장소에 저장된 apk 파일 자동 업데이트 수행
투케이2K 2023. 10. 22. 19:58[개발 환경 설정]
개발 툴 : AndroidStudio
[소스 코드]
// -----------------------------------------------------------------------------------------
// TODO [SEARCH FAST] : [RETURN] update_External_Apk_File : 외부 저장소 경로에 저장된 APK 파일 사용해 앱 업데이트 수행
// -----------------------------------------------------------------------------------------
public static Boolean update_External_Apk_File(Context mContext, String apk_path) {
/**
* // -----------------------------------------
* [update_External_Apk_File 메소드 설명]
* // -----------------------------------------
* 1. TODO 설 명 :
*
* 외부 저장소 경로에 저장된 APK 파일 사용해 앱 업데이트 수행
* // -----------------------------------------
* 2. TODO 호출 방식 :
*
* try {
*
* // ----------------------------------------
*
* // TODO [외부 저장소 경로 확인]
* String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
* String folderName = "LOG_SAVE_FOLDER";
* String fileName = "update_test.apk";
*
* // ----------------------------------------
*
* // TODO [다운로드 폴더에서 세부 경로 정의]
* if (filePath.endsWith("/") == true){
* filePath = filePath + folderName;
* }
* else {
* filePath = filePath + "/" + folderName;
* }
*
* if (filePath.endsWith("/") == true){
* filePath = filePath + fileName;
* }
* else {
* filePath = filePath + "/" + fileName;
* }
*
* // ----------------------------------------
*
* // TODO [apk 파일 업데이트 수행 실시 : 조건은 빌드를 수행한 프로젝트와 같은 패키지 명칭을 가진 동일 앱]
* C_App.update_External_Apk_File(A_Webview.this, filePath);
*
* // ----------------------------------------
*
* }
* catch (Exception e) {
* S_Log._printStackTrace_(A_Webview.this, S_FinalMsg.LOG_BUG_STATE, null, e);
* }
*
* // -----------------------------------------
* 3. TODO 리턴 데이터 :
*
* apk 파일 업데이트 가능 시 true / 아니면 false
* // -----------------------------------------
* 4. TODO 추가로 외부 저장소에 파일 읽기 및 쓰기를 위해서 Manifest 권한 필요 및 인텐트 이동 수행
*
* 권한 : <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
*
* 인텐트 이동 : Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
* // -----------------------------------------
* 5. TODO 출처를 알 수 없는 앱 설치 허용 퍼미션 권한 필요 및 인텐트 이동 수행
*
* 권한 : <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
*
* 인텐트 이동 : Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES
* // -----------------------------------------
* 6. TODO AndroidManifest.xml 파일 및 xml 설정 관련
* // -----------------------------------------
* [AndroidManifest.xml 파일]
*
* <application
*
* <!-- ============================================================= -->
* <!-- [프로 바인더 지정 : 외부 저장소 접근] -->
* <!-- ============================================================= -->
* <provider
* android:name="androidx.core.content.FileProvider"
* android:authorities="${applicationId}.provider"
* android:exported="false"
* android:grantUriPermissions="true">
* <meta-data
* android:name="android.support.FILE_PROVIDER_PATHS"
* android:resource="@xml/provider_paths" />
* </provider>
* </application>
* // -----------------------------------------
* [provider_paths.xml 설정]
*
* <?xml version="1.0" encoding="utf-8"?>
* <paths>
*
* <!-- [외부 저장소 접근] -->
* <external-path name="external_files" path="."/>
*
* </paths>
* // -----------------------------------------
* 7. TODO 참고 설명 :
*
* 해당 권한을 추가 시 마켓에 특정 용도로 사용하는 앱 목적을 밝혀야합니다 (앱 등록 및 업데이트 리젝 될 수 있습니다)
*
* 외부 저장소 경로 : /storage/emulated/0
* // -----------------------------------------
* */
// [리턴 값 선언]
boolean returnData = false;
String M_LOG = "";
// [로직 처리 실시]
try {
// [데이터 널 체크]
if (C_Util.stringNotNull(apk_path) == true){
// [apk 및 aab 파일 확장자 명 확인]
if (apk_path.toLowerCase().contains(".apk") == true || apk_path.toLowerCase().contains(".aab") == true){
// [File 사용해 해당 경로에 실제 파일이 존재 하는지 확인]
File file = new File(apk_path);
if (file.exists() == true){
// [매니저 파일 권한 부여 체크 실시]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& Environment.isExternalStorageManager() == true){ // [안드로이드 11 이상]
// [외부앱 설치 허용 확인]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& mContext.getPackageManager().canRequestPackageInstalls() == true){
// [apk 앱 파일 설치 및 업데이트 진행]
Intent intent = new Intent(Intent.ACTION_VIEW);
//Uri apkUri = Uri.fromFile(file);
Uri apkUri = FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".provider", file);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
mContext.startActivity(intent);
// [리턴 변수 선언 및 업데이트]
returnData = true;
}
else {
M_LOG = "[ERROR] :: Request Package Install Permission Error";
// [외부앱 설치 허용 인텐트 이동]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setData(Uri.parse(String.format("package:%s", mContext.getPackageName())));
mContext.startActivity(intent);
}
}
}
else {
M_LOG = "[ERROR] :: External Storage Permission Error";
// [매니저 파일 권한 부여 인텐트 이동]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setData(Uri.parse(String.format("package:%s", mContext.getPackageName())));
mContext.startActivity(intent);
}
}
}
else {
M_LOG = "[ERROR] :: Apk File Not Exists";
}
}
else {
M_LOG = "[ERROR] :: Apk File Extension Not Found";
}
}
else {
M_LOG = "[ERROR] :: Input Apk File Path Is Null";
}
} catch (Exception e) {
S_Log._printStackTrace_(mContext, S_FinalMsg.LOG_BUG_STATE, null, e);
M_LOG = "[Exception] :: " + String.valueOf(e.getMessage());
}
// [로그 출력 실시]
// ===============================================================
S_Log._D_("외부 저장소 경로에 저장된 APK 파일 사용해 앱 업데이트 수행", new String[]{
"INPUT [PATH] :: " + String.valueOf(apk_path),
"M_LOG :: " + String.valueOf(M_LOG),
"RETURN :: " + String.valueOf(returnData)
});
// ===============================================================
// [리턴 반환 실시]
return returnData;
}
[결과 출력]
반응형
'Android' 카테고리의 다른 글
Comments