답변:
Play 스토어 링크 또는 설치 프롬프트를 쉽게 시작할 수 있습니다.
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse("content:///path/to/your.apk"),
"application/vnd.android.package-archive");
startActivity(promptInstall);
또는
Intent goToMarket = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.package.name"));
startActivity(goToMarket);
그러나 사용자의 명시 적 허가 없이는 .apks를 설치할 수 없습니다 . 장치와 프로그램이 루팅되지 않는 한 아닙니다.
/sdcard
.Android 2.2 이상 및 기타 기기에서는 잘못 되었기 때문입니다. Environment.getExternalStorageDirectory()
대신 사용하십시오 .
File file = new File(dir, "App.apk");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
나는 같은 문제가 있었고 여러 번 시도한 후에 이런 식으로 나에게 도움이되었습니다. 이유를 모르겠지만 데이터와 유형을 별도로 설정하면 의도가 악화되었습니다.
setData()
유형 매개 변수가 제거됨). setDataAndType()
둘 다에 값을 제공하려면 반드시 사용해야 합니다. 여기 : developer.android.com/reference/android/content/…
이 질문에 제공된 해결책은 모두 targetSdkVersion
23 이하에 적용 됩니다. 그러나 Android N, 즉 API 레벨 24 이상에서는 다음 예외와 함께 작동하지 않으며 충돌합니다.
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
이것은 Android 24부터 Uri
다운로드 파일의 주소 지정이 변경 되었기 때문 입니다. 예를 들어 appName.apk
패키지 이름을 가진 앱의 기본 외부 파일 시스템에 저장된 설치 파일 com.example.test
은 다음과 같습니다.
file:///storage/emulated/0/Android/data/com.example.test/files/appName.apk
에 API 23
, 아래 같은 반면,
content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk
대한 API 24
이상.
이것에 대한 자세한 내용은 여기 에서 찾을 수 있으며 나는 그것을 거치지 않을 것입니다.
에 대한 질문에 대답하기 targetSdkVersion
의 24
이상, 하나는 다음 단계를 수행하는 다음의 AndroidManifest.xml에 다음을 추가합니다 :
<application
android:allowBackup="true"
android:label="@string/app_name">
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.authorityStr"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
</application>
2. src, main paths.xml
의 xml
폴더에 다음 파일을 추가하십시오 res
.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="pathName"
path="pathValue"/>
</paths>
이는 pathName
위의 예시적인 컨텐츠 uri 예 pathValue
에 표시된 것이며 시스템의 실제 경로입니다. "."를 넣는 것이 좋습니다. 추가 서브 디렉토리를 추가하지 않으려는 경우 위의 pathValue에 대해 (따옴표없이).
appName.apk
기본 외부 파일 시스템에 이름 으로 apk를 설치하려면 다음 코드를 작성하십시오 .
File directory = context.getExternalFilesDir(null);
File file = new File(directory, fileName);
Uri fileUri = Uri.fromFile(file);
if (Build.VERSION.SDK_INT >= 24) {
fileUri = FileProvider.getUriForFile(context, context.getPackageName(),
file);
}
Intent intent = new Intent(Intent.ACTION_VIEW, fileUri);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.setDataAndType(fileUri, "application/vnd.android" + ".package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
activity.finish();
외부 파일 시스템에서 자신의 앱의 개인 디렉토리에 쓸 때도 권한이 필요하지 않습니다.
나는 자동 업데이트 라이브러리를 작성했습니다 여기에 내가 위의 내용을 사용하고있는.
.authorityStr
후 context.getPackageName()
다음 작업을해야합니다.
글쎄, 나는 더 깊이 파고 안드로이드 소스에서 PackageInstaller 응용 프로그램의 소스를 찾았습니다.
https://github.com/android/platform_packages_apps_packageinstaller
매니페스트에서 권한이 필요하다는 것을 알았습니다.
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
그리고 실제 설치 과정은 확인 후 발생합니다.
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class);
String installerPackageName = getIntent().getStringExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);
}
startActivity(newIntent);
내 apk 파일이 내 앱 "Data"디렉토리에 저장되었고 apk 파일에 대한 권한을 세상에 읽을 수 있도록 변경하여 그와 같은 방식으로 설치해야한다는 사실을 공유하고 싶습니다. "구문 분석 오류 : 패키지를 구문 분석하는 중에 문제점이 발생했습니다"; @Horaceman의 솔루션을 사용하여 다음을 수행하십시오.
File file = new File(dir, "App.apk");
file.setReadable(true, false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
이것은 다른 사람들을 많이 도울 수 있습니다!
먼저:
private static final String APP_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyAppFolderInStorage/";
private void install() {
File file = new File(APP_DIR + fileName);
if (file.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
String type = "application/vnd.android.package-archive";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri downloadedApk = FileProvider.getUriForFile(getContext(), "ir.greencode", file);
intent.setDataAndType(downloadedApk, type);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(file), type);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
getContext().startActivity(intent);
} else {
Toast.makeText(getContext(), "ّFile not found!", Toast.LENGTH_SHORT).show();
}
}
둘째 : 안드로이드 7 이상에서는 아래와 같이 매니페스트에 공급자를 정의해야합니다!
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="ir.greencode"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths" />
</provider>
셋째 : 아래와 같이 res / xml 폴더에 path.xml을 정의하십시오! 다른 방법으로 변경하려면 내부 스토리지 에이 경로 를 사용 하고 있습니다. 이 링크로 이동할 수 있습니다 : FileProvider
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="your_folder_name" path="MyAppFolderInStorage/"/>
</paths>
넷째 : 이 권한을 매니페스트에 추가해야합니다.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
애플리케이션이 패키지 설치를 요청할 수 있도록합니다. Intent.ACTION_INSTALL_PACKAGE를 사용하려면 25보다 큰 API를 대상으로하는 앱이이 권한을 보유해야합니다.
공급 업체 권한이 동일한 지 확인하십시오!
네 가능합니다. 그러나 확인되지 않은 소스를 설치하려면 전화가 필요합니다. 예를 들어 slideMe가 그렇게합니다. 나는 당신이 할 수있는 가장 좋은 방법은 응용 프로그램이 있는지 확인하고 Android 마켓에 대한 의도를 보내는 것입니다. 당신은 안드로이드 마켓에 대한 URL 체계를 사용해야합니다.
market://details?id=package.name
활동을 시작하는 방법을 정확히 모르지만 해당 URL로 활동을 시작하는 경우. 안드로이드 마켓을 열고 앱을 설치할 수있는 옵션을 제공해야합니다.
를 사용 DownloadManager
하여 다운로드를 시작하는 경우 외부 위치 (예 :)에 저장해야합니다 setDestinationInExternalFilesDir(c, null, "<your name here>).apk";
. 패키지 아카이브 유형의 의도 content:
는 내부 위치로 다운로드하는 데 사용되는 체계 를 좋아하지 않는 것처럼 보이지만 좋아 file:
합니다. ( file:
앱이 apk를 구문 분석하지 않기 때문에 URL을 생성하더라도 내부 경로를 File 객체로 래핑 한 다음 경로를 가져 오는 것도 작동하지 않습니다 . 외부이어야합니다.)
예:
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
File mFile = new File(Uri.parse(downloadedPackageUriString).getPath());
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
appContext.startActivity(promptInstall);
권한을 요청하는 것을 잊지 마십시오 :
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
android.Manifest.permission.READ_EXTERNAL_STORAGE
AndroidManifest.xml에 제공자 및 권한을 추가하십시오.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
XML 파일 제공자 res / xml / provider_paths.xml 작성
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
아래 예제 코드를 사용하십시오.
public class InstallManagerApk extends AppCompatActivity {
static final String NAME_APK_FILE = "some.apk";
public static final int REQUEST_INSTALL = 0;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// required permission:
// android.Manifest.permission.WRITE_EXTERNAL_STORAGE
// android.Manifest.permission.READ_EXTERNAL_STORAGE
installApk();
}
...
/**
* Install APK File
*/
private void installApk() {
try {
File filePath = Environment.getExternalStorageDirectory();// path to file apk
File file = new File(filePath, LoadManagerApkFile.NAME_APK_FILE);
Uri uri = getApkUri( file.getPath() ); // get Uri for each SDK Android
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( uri );
intent.setFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK );
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
intent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, getApplicationInfo().packageName);
if ( getPackageManager().queryIntentActivities(intent, 0 ) != null ) {// checked on start Activity
startActivityForResult(intent, REQUEST_INSTALL);
} else {
throw new Exception("don`t start Activity.");
}
} catch ( Exception e ) {
Log.i(TAG + ":InstallApk", "Failed installl APK file", e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)
.show();
}
}
/**
* Returns a Uri pointing to the APK to install.
*/
private Uri getApkUri(String path) {
// Before N, a MODE_WORLD_READABLE file could be passed via the ACTION_INSTALL_PACKAGE
// Intent. Since N, MODE_WORLD_READABLE files are forbidden, and a FileProvider is
// recommended.
boolean useFileProvider = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
String tempFilename = "tmp.apk";
byte[] buffer = new byte[16384];
int fileMode = useFileProvider ? Context.MODE_PRIVATE : Context.MODE_WORLD_READABLE;
try (InputStream is = new FileInputStream(new File(path));
FileOutputStream fout = openFileOutput(tempFilename, fileMode)) {
int n;
while ((n = is.read(buffer)) >= 0) {
fout.write(buffer, 0, n);
}
} catch (IOException e) {
Log.i(TAG + ":getApkUri", "Failed to write temporary APK file", e);
}
if (useFileProvider) {
File toInstall = new File(this.getFilesDir(), tempFilename);
return FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, toInstall);
} else {
return Uri.fromFile(getFileStreamPath(tempFilename));
}
}
/**
* Listener event on installation APK file
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_INSTALL) {
if (resultCode == Activity.RESULT_OK) {
Toast.makeText(this,"Install succeeded!", Toast.LENGTH_SHORT).show();
} else if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this,"Install canceled!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"Install Failed!", Toast.LENGTH_SHORT).show();
}
}
}
...
}
이 시도
String filePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
String title = filePath.substring( filePath.lastIndexOf('/')+1, filePath.length() );
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
MainActivity.this.startActivity(intent);
먼저 AndroidManifest.xml에 다음 행을 추가하십시오.
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
그런 다음 다음 코드를 사용하여 apk를 설치하십시오.
File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/MyApp";// + "app-release.apk";
File file = new File(fileStr, "TaghvimShamsi.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
startActivity(promptInstall);
UpdateNode 는 다른 앱 내부에서 APK 패키지를 설치하기위한 Android 용 API를 제공합니다.
온라인으로 업데이트를 정의하고 API를 앱에 통합하면됩니다.
현재 API는 베타 상태이지만 이미 일부 테스트를 직접 수행 할 수 있습니다.
그 외에도 UpdateNode는 시스템을 통해 메시지를 표시합니다. 사용자에게 중요한 정보를 말하려는 경우 매우 유용합니다.
나는 클라이언트 개발 팀의 일원이며 적어도 내 안드로이드 앱에 메시지 기능을 사용하고 있습니다.
이것을 시도하십시오-매니페스트에 쓰기 :
uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions"
코드를 작성하십시오 :
File sdCard = Environment.getExternalStorageDirectory();
String fileStr = sdCard.getAbsolutePath() + "/Download";// + "app-release.apk";
File file = new File(fileStr, "app-release.apk");
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
startActivity(promptInstall);