4

I'm trying to code a proof of concept, with Xamarin android. A sort of EMM tool, i.e. an application which will be in charge of installing other applications and managing the device. So Android Marshmallow is a good place to start with android for work features.

My app is a Device Owner, therefore it should have no problem silently installing other applications. It can download an apk from a website without any problem. But when I try to install it, it throws a "Files still open" exception despite calling all Close() methods.

I have taken my code from the excellent android-testdpc github example here.

I have changed it to work in C# with Xamarin.

Here is my code:

    public static bool InstallPackage(Context context, Handler handler, InputStream input, String packageName)
    {
        try
        {
            PackageInstaller packageInstaller = context.PackageManager.PackageInstaller;
            PackageInstaller.SessionParams param = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
            param.SetAppPackageName(packageName);
            // set params
            int sessionId = packageInstaller.CreateSession(param);
            PackageInstaller.Session session = packageInstaller.OpenSession(sessionId);
            using (System.IO.Stream output = session.OpenWrite("COSU", 0, -1))
            {
                byte[] buffer = new byte[65536];
                int c;
                while ((c = input.Read(buffer)) != -1)
                {
                    output.Write(buffer, 0, c);
                }
                session.Fsync(output);
                input.Close();
                output.Close();
            }
            session.Commit(createIntentSender(context, sessionId)); // this line throws exception 'Files stil open'
            return true;
        }
        catch (Exception ex)
        {
            Log.Error(TAG, "Error installing package: " + packageName, ex);
            handler.SendMessage(handler.ObtainMessage(Common.MSG_INSTALL_FAIL,
                    packageName));
            return false;
        }
    }

I'm stuck with this for the moment. If I have the time, I will try to install Android Studio and test my code in Java to see if the problem comes from Xamarin.

If someone has any clue for my problem, I will greatly appreciate the help.

Bondolin
  • 2,793
  • 7
  • 34
  • 62
Mathieu
  • 516
  • 2
  • 10
  • FWIW - I have added a working, albeit simple Xamarin translation here - https://stackoverflow.com/a/69774124/1399272 – Bondolin Oct 29 '21 at 20:14

1 Answers1

3

SecurityException : if streams opened through openWrite(String, long, long) are still open.

The Java peer object is not closed yet, this is how I force it for the PackageInstaller.Session.Commit:

var input = Assets.Open(packageName);
var packageInstaller = PackageManager.PackageInstaller;
var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
sessionParams.SetAppPackageName(packageName);
int sessionId = packageInstaller.CreateSession(sessionParams);
var session = packageInstaller.OpenSession(sessionId);
using (var output = session.OpenWrite(packageName, 0, -1))
{
    input.CopyTo(output);
    session.Fsync(output);
    foreach (var name in session.GetNames())
        Log.Debug("Installer", name);
    output.Close();
    output.Dispose();
    input.Close();
    input.Dispose();
    GC.Collect();
}
var pendingIntent = PendingIntent.GetBroadcast(BaseContext, sessionId, new Intent(Intent.ActionInstallPackage), 0);
session.Commit(pendingIntent.IntentSender);
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • 1
    Thanks ! I'm a little disturb by this call of the garbage collector but since it works... – Mathieu Aug 22 '16 at 07:54
  • 1
    unfortunately this stopped working when using android sdk version Q 10. Then this code results in an error message "write failed: EBADF (Bad file descriptor)" – smedasn Mar 25 '20 at 15:06