Pregunta

I am trying to create an app that installs another .apk file from assets.

var tmpPath = Android.OS.Environment.ExternalStorageDirectory.Path + "/tmp_app.apk";
using (var asset = Assets.Open("Test/Cnd.apk")) using (var dest = File.Create (tmpPath))       asset.CopyTo (dest);
Intent setupIntent = new Intent(Intent.ActionView);
setupIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(tmpPath))); 
setupIntent.SetType("application/vnd.android.package-archive"); 
StartActivity(setupIntent);

But If I run it at emulator I got "No activity found to handle intent" exception. If I run it at mobile device I got "Java.Lang.Throwable" exception. I checked sdcard at device, so file was successfully copied from assets and exists.

¿Fue útil?

Solución

Instead of using the SetData and SetType methods you need to use SetDataAndType. I have no idea why this works opposed to setting them separately but it does.

Intent setupIntent = new Intent(Intent.ActionView);
setupIntent.SetDataAndType(Android.Net.Uri.FromFile(new Java.IO.File(tmpPath)), "application/vnd.android.package-archive");
StartActivity(setupIntent);

See: Install Application programmatically on Android

You also need to include the INSTALL_PACKAGES permission into your manifest, you can do this in Xamarin through the Project Options->Android Application->Required Permissions menu.

Bonus Answer

I also noticed that the method you use to extract your apk won't work. The code using (var asset = Assets.Open("Test/Cnd.apk")) using (var dest = File.Create (tmpPath)) will create an empty file named tmp_app.apk in your external storage path. When the package manager attempts to install it, it will fail with a Parse Error.

To fix this, do a binary copy of the APK out of the Assets directory like so:

string apkPath = Path.Combine (Android.OS.Environment.ExternalStorageDirectory.ToString (), "tmp_app.apk");
using (BinaryReader br = new BinaryReader(Assets.Open("Test/Cnd.apk")))
{
    using (BinaryWriter bw = new BinaryWriter(new FileStream(apkPath, FileMode.Create)))
    {
        byte[] buffer = new byte[2048];
        int len = 0;
        while ((len = br.Read(buffer, 0, buffer.Length)) > 0)
        {
            bw.Write (buffer, 0, len);
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top