para - Instalar la aplicación programáticamente en Android
uptodown (14)
Bueno, investigué más profundamente y encontré fuentes de la aplicación PackageInstaller de Android Source.
https://github.com/android/platform_packages_apps_packageinstaller
De manifiesto encontré que requiere permiso:
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
Y el proceso real de instalación ocurre después de la confirmación
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);
Me interesa saber si es posible instalar mediante programación una aplicación apk descargada dinámicamente de una aplicación personalizada de Android.
Las soluciones proporcionadas a esta pregunta son todas aplicables a targetSdkVersion
s de 23 y siguientes. Para Android N, es decir, nivel API 24 y superior, sin embargo, no funcionan y se bloquean con la siguiente excepción:
android.os.FileUriExposedException: file:///storage/emulated/0/... exposed beyond app through Intent.getData()
Esto se debe al hecho de que a partir de Android 24, el Uri
para abordar el archivo descargado ha cambiado. Por ejemplo, un archivo de instalación llamado appName.apk
almacenado en el sistema de archivos externo primario de la aplicación con el nombre del paquete com.example.test
sería como
file:///storage/emulated/0/Android/data/com.example.test/files/appName.apk
para API 23
y abajo, mientras que algo como
content://com.example.test.authorityStr/pathName/Android/data/com.example.test/files/appName.apk
para API 24
y superior.
Se pueden encontrar más detalles sobre esto here y no voy a revisarlo.
Para responder a la pregunta sobre targetSdkVersion
de 24
y superior, debe seguir estos pasos: Agregue lo siguiente a 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. Agregue el siguiente archivo paths.xml
a la carpeta xml
en res
en src, main:
<?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
es el que se muestra en el ejemplo de ejemplo de uri de ejemplo anterior y pathValue
es la ruta real en el sistema. Sería una buena idea poner un "." (sin comillas) para pathValue en el cuadro anterior si no desea agregar ningún subdirectorio adicional.
Escriba el siguiente código para instalar el apk con el nombre
appName.apk
en el sistema de archivos externo principal: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();
No se requiere permiso al escribir en el directorio privado de su propia aplicación en el sistema de archivos externo.
He escrito una biblioteca de AutoUpdate here en la que he usado lo anterior.
Otra solución que no requiere codificar la aplicación receptora y que, por lo tanto, es más segura:
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData( Uri.fromFile(new File(pathToApk)) );
startActivity(intent);
Primero agregue la siguiente línea a AndroidManifest.xml:
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
A continuación, use el siguiente código para instalar 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);
Prueba esto - Escribe en Manifiesto:
uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions"
Escribe el código:
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);
Puede iniciar fácilmente un enlace de mercado o un indicador de instalación:
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse("file:///path/to/your.apk"),
"application/vnd.android.package-archive");
startActivity(promptInstall);
Intent goToMarket = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("market://details?id=com.package.name"));
startActivity(goToMarket);
Sin embargo, no puede instalar .apks sin el permiso explícito del usuario; no, a menos que el dispositivo y su programa estén rooteados.
Si es posible. Pero para eso necesita que el teléfono instale fuentes no verificadas. Por ejemplo, slideMe hace eso. Creo que lo mejor que puedes hacer es comprobar si la aplicación está presente y enviar un intento para Android Market. deberías usar algo el esquema de url para Android Market.
market://details?id=package.name
No sé exactamente cómo comenzar la actividad, pero si comienzas una actividad con ese tipo de url. Debería abrir el mercado de Android y darle la opción de instalar las aplicaciones.
Sigue estos pasos:
1 - Agregue lo siguiente a AndroidManifest.xml
:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/paths"/>
</provider>
2 - Agregue el siguiente archivo paths.xml a la carpeta xml (si no existe, créelo) en res en src, main
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_file"
path="."/>
</paths>
PathName es el que se muestra en el ejemplo de ejemplo de uri de ejemplo anterior y pathValue es la ruta real en el sistema. Sería una buena idea poner un "." para pathValue en lo anterior si no desea agregar ningún subdirectorio adicional.
3 - Escribe el siguiente código para ejecutar tus archivos apk:
File file = "path of yor apk file";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri fileUri = FileProvider.getUriForFile(getBaseContext(), getApplicationContext().getPackageName() + ".provider", 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);
startActivity(intent);
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
Y gracias a Ali Nemati Hayati por ser la primera en escribir el solución
Solo quiero compartir el hecho de que mi archivo apk se guardó en el directorio de "Datos" de mi aplicación y que necesitaba cambiar los permisos en el archivo apk para que sea legible a nivel mundial para permitir que se instale de esa manera; de lo contrario, el sistema lanzaba "Error de análisis: hay un problema al analizar el paquete"; entonces usando la solución de @Horaceman eso hace:
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);
Solo una extensión, si alguien necesita una biblioteca, this podría ayudar. Gracias a Raghav
Vale la pena señalar que si utiliza el DownloadManager
para iniciar la descarga, asegúrese de guardarlo en una ubicación externa, por ejemplo, setDestinationInExternalFilesDir(c, null, "<your name here>).apk";
. Al intento con un tipo de paquete-archivo no parece gustarle el content:
esquema utilizado con descargas en una ubicación interna, pero sí como file:
(Intentar envolver la ruta interna en un objeto File y luego obtener la ruta tampoco funciona, a pesar de que da como resultado un file:
url, ya que la aplicación no analiza el apk; parece que debe ser externo).
Ejemplo:
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);
prueba esto
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);
UpdateNode proporciona una API para Android para instalar paquetes APK desde otra aplicación.
Puede simplemente definir su actualización en línea e integrar la API en su aplicación, eso es todo.
Actualmente, la API está en estado Beta, pero usted mismo puede hacer algunas pruebas.
Además de eso, UpdateNode también ofrece mensajes a través del sistema, bastante útil si quieres contar algo importante a tus usuarios.
Soy parte del equipo de desarrollo de clientes y estoy usando al menos la funcionalidad de mensajes para mi propia aplicación de Android.
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);
Tuve el mismo problema y después de varios intentos, funcionó para mí de esta manera. No sé por qué, pero configurar datos y escribirlos por separado arruinó mi intención.