I'm tertarik untuk mengetahui jika itu adalah mungkin untuk pemrograman menginstal secara dinamis download apk dari aplikasi Android kustom.
Anda dapat dengan mudah meluncurkan play store link atau menginstal prompt:
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse("content:///path/to/your.apk"),
"application/vnd.android.package-archive");
startActivity(promptInstall);
atau
Intent goToMarket = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.package.name"));
startActivity(goToMarket);
Namun, anda tidak dapat menginstal .apk tanpa user's izin eksplisit; tidak, kecuali perangkat dan program anda berakar.
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);
Aku punya masalah yang sama dan setelah beberapa kali mencoba, itu bekerja untuk saya dengan cara ini. Saya don't tahu mengapa, tapi pengaturan data dan jenis secara terpisah kacau saya maksud.
Solusi yang diberikan untuk pertanyaan ini semua berlaku untuk targetSdkVersion
s 23 dan di bawah ini. Untuk Android N, yaitu API level 24, dan di atas, namun, mereka tidak bekerja dan kecelakaan dengan Pengecualian berikut:
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
Ini adalah karena fakta bahwa mulai dari Android 24, Uri
untuk mengatasi file yang didownload telah berubah. Sebagai contoh, sebuah instalasi file bernama appName.apk
yang tersimpan di eksternal utama filesystem dari aplikasi dengan nama paket com.contoh.tes
akan menjadi seperti
file:///storage/emulated/0/Android/data/com.contoh.tes/file/namaaplikasi.apk
untuk API 23
dan di bawah ini, sedangkan sesuatu seperti
content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk
untuk API 24
dan di atas.
Rincian lebih lanjut tentang hal ini dapat ditemukan di sini dan aku tidak akan pergi melalui itu.
Untuk menjawab pertanyaan untuk targetSdkVersion
dari 24
dan di atas, kita harus ikuti langkah-langkah berikut:
Tambahkan baris berikut ke 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>
paths.xml
file xml
folder pada res
di src, utama:<?xml version="1.0" encoding="utf-8"?>
<jalan xmlns:android="http://schemas.android.com/apk/res/android">path
adalah yang ditampilkan di teladan konten uri contoh di atas dan pathValue
adalah jalan yang sebenarnya pada sistem.
Itu akan menjadi ide yang baik untuk menempatkan "." (tanpa tanda kutip) untuk pathValue di atas jika anda tidak ingin menambahkan tambahan subdirektori.
appName.apk
pada primer eksternal filesystem:Direktori File = konteks.getExternalFilesDir(null); File file = new File(directory, fileName); Uri fileUri = Uri.fromFile(file); jika (Membangun.VERSI.SDK_INT >= 24) { fileUri = FileProvider.getUriForFile(konteks, konteks.getPackageName(), file); } Intent intent = new Intent(Intent.ACTION_VIEW, fileUri); maksud.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); maksud.setDataAndType(fileUri, "aplikasi/vnd.android" + ".paket-arsip"); maksud.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Maksud.FLAG_ACTIVITY_NEW_TASK); maksud.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); konteks.startActivity(intent); kegiatan.finish();
Tidak ada izin juga diperlukan ketika menulis untuk aplikasi anda sendiri's pribadi direktori eksternal pada filesystem.
Saya telah menulis sebuah Perbaharui perpustakaan di sini di mana saya telah digunakan di atas.
Nah, saya menggali lebih dalam, dan menemukan sumber-sumber PackageInstaller aplikasi Android dari Sumber.
https://github.com/android/platform_packages_apps_packageinstaller
Dari manifest saya menemukan bahwa hal itu memerlukan izin:
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
Dan sebenarnya proses instalasi terjadi setelah konfirmasi
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);
Saya hanya ingin berbagi fakta bahwa saya apk file yang telah disimpan ke aplikasi saya "Data" direktori dan bahwa saya perlu untuk mengubah hak akses pada file apk untuk dibaca dalam rangka untuk memungkinkan untuk dipasang dengan cara itu, jika sistem itu melempar "Parse error: There is a Problem Parsing the Package"; jadi menggunakan solusi dari @Horaceman yang membuat:
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);
Hal ini dapat membantu orang lain banyak!
Pertama:
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();
}
}
Kedua: Untuk android 7 dan di atas, anda harus menentukan penyedia dalam manifest seperti di bawah ini!
<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>
Ketiga: Tentukan path.xml di res/xml folder seperti di bawah ini! I'm menggunakan ini jalan untuk penyimpanan internal jika anda ingin mengubahnya ke sesuatu yang lain ada beberapa cara! Anda dapat pergi ke link ini: 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>
Balik: Anda harus menambahkan izin ini menyatakan:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
Memungkinkan aplikasi untuk permintaan menginstal paket. Aplikasi yang menargetkan Api lebih besar dari 25 harus memegang izin ini dalam rangka untuk menggunakan Intent.ACTION_INSTALL_PACKAGE.
pastikan penyedia otoritas yang sama!
Solusi lain yang doesn't tidak memerlukan kode keras menerima aplikasi dan yang karena itu lebih aman:
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( Uri.fromFile(new File(pathToApk)) );
startActivity(intent);
Ya itu's mungkin. Tapi untuk itu anda perlu telepon untuk menginstal sumber yang belum diverifikasi. Misalnya, slideMe melakukan itu. Saya pikir hal terbaik yang dapat anda lakukan adalah untuk memeriksa apakah aplikasi ini hadir dan mengirim intent untuk Pasar Android. anda harus menggunakan sesuatu skema url untuk Pasar android.
market://details?id=package.name
Saya don't tahu bagaimana untuk memulai aktivitas tetapi jika anda memulai aktivitas dengan jenis url. Ini harus buka android market dan memberikan anda pilihan untuk menginstal aplikasi.
It's dicatat bahwa jika anda menggunakan DownloadManager
untuk memulai download anda, pastikan untuk menyimpannya ke lokasi eksternal misal setDestinationInExternalFilesDir(c, null, "<nama anda di sini>).apk";
. Maksud dengan paket-jenis arsip doesn't tampak seperti content:
skema yang digunakan dengan popularitas internal lokasi, tapi tidak seperti file:
. (Mencoba untuk membungkus internal path ke File objek dan kemudian mendapatkan jalan doesn't bekerja dengan baik, meskipun hasil di file:
url, seperti aplikasi tidak't mengurai apk; sepertinya harus eksternal.)
Contoh:
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);
coba ini
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);
Hanya perpanjangan, jika ada yang perlu perpustakaan kemudian ini mungkin bisa membantu. Terima kasih untuk Raghav
UpdateNode menyediakan API untuk Android untuk menginstal APK paket dari dalam Aplikasi lain.
Anda hanya dapat menentukan anda Update secara online dan mengintegrasikan API ke dalam Aplikasi anda - yang's ini.
Saat ini API di negara Beta, tetapi anda sudah dapat melakukan beberapa tes diri anda.
Selain itu, UpdateNode ini juga menampilkan pesan meskipun sistem ini cukup berguna jika anda ingin mengatakan sesuatu yang penting untuk anda pengguna.
Saya adalah bagian dari klien dev team, dan saya menggunakan setidaknya pesan fungsi untuk saya sendiri Aplikasi Android.
Lihat berikut keterangan bagaimana untuk mengintegrasikan API
Pertama tambahkan baris berikut ke AndroidManifest.xml :
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
Kemudian gunakan kode berikut untuk menginstal 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);
Jangan lupa untuk meminta izin:
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
android.Manifest.permission.READ_EXTERNAL_STORAGE
Tambahkan di AndroidManifest.xml penyedia dan izin:
<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>
Membuat file XML penyedia 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>
Gunakan di bawah ini contoh kode:
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();
}
}
}
...
}
Coba ini
uses-permission android:name="android.izin.INSTALL_PACKAGES" alat-alat:mengabaikan="ProtectedPermissions"
Menulis Kode:
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);