Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question FileProvider added via AndroidManifest.xml prevents my app from running

Discussion in 'Android' started by Stericraft, May 6, 2024.

  1. Stericraft

    Stericraft

    Joined:
    Sep 25, 2020
    Posts:
    6
    Hi everyone, :)

    I took a quick look at the forums rules for this first post of mine, but feel free to inform me of any missing information.

    Goal
    I'm coding a Unity Android App, in which I want to implement an auto-update functionality. After Unity has downloaded the updated version of my app from a server, I want it to open it programmatically.
    On Unity side, everything works fine (I can call custom made java functions from my *.aar file). On Android Studio side (which I'm using for the first time), I'm implementing a "OpenApk()" method.

    Here is what I import to use Android tools:

    import androidx.core.content.FileProvider;
    import android.content.Context;
    import android.content.Intent;
    import android.net.Uri;
    import java.io.File;


    Here is my function in Android Studio:

    Code (JavaScript):
    1. public void openApkFile(String _filePath) {
    2.    try {
    3.        File apkFullPath = new File(context.getFilesDir() + File.separator + _filePath);
    4.        Uri apkUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", apkFullPath);
    5.        Intent intent = new Intent(Intent.ACTION_VIEW);
    6.  
    7.        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    8.        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    9.        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    10.  
    11.        context.startActivity(intent);
    12.    }
    13.    catch (Exception e) {
    14.        printToastMessage(e.toString(), true);
    15.    }
    16. }
    Here is my AndroidManifest.xml (Android Studio side, no custom one is used on Unity side):
    Code (Boo):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.opu.intranet"> <!-- I ADDED MY PACKAGE NAME HERE -->
    3.    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    4.  
    5.    <!-- ADDING THIS PROVIDER VIA XML PREVENTS APP FROM RUNNING (CRASH ON EXECUTION) -->
    6.    <application>
    7.        <provider
    8.            android:name="androidx.core.content.FileProvider"
    9.            android:authorities="${applicationId}.fileprovider"
    10.            android:exported="false"
    11.            android:grantUriPermissions="true">
    12.            <meta-data
    13.                android:name="android.support.FILE_PROVIDER_PATHS"
    14.                android:resource="@xml/file_paths" />
    15.        </provider>
    16.    </application>
    17. </manifest>

    Also I added:

    android.useAndroidX=true # WAS ALREADY PRESENT BY DEFAULT
    android.enableJetifier=true


    to gradle.properties (still on Android Studio side).

    Problem

    Whenever I build my *.aar package and add it to Unity, if the AndroidManifest.xml file contains a reference to a file provider, the app won't run anymore on my phone. It closes immediately after opening, and the OS asks me to wait for the developer to solve the problem haha. :D
    Here is the log cat of my smartphone when I try to open the app:

    Unable to get provider androidx.core.content.FileProvider: java.lang.ClassNotFoundException: Didn't find class "androidx.core.content.FileProvider"


    Software versions
    Unity: 2022.3.20f1
    Android Studio: 2023.2.1
    Gradle: 7.1.2 on Unity side, 8.4 on Android Studio side Android: 14 (API 34)
    Target SDK : API 24 or higher

    Fix attempts
    I spent 2 days reading similar discussions about this everywhere, and testing multiple combinations. I even unzipped AndroidFileOpener (See here) by Mihail5412, a plugin I used before but stopped working after a while (Unity Editor package rename errors).

    I tried using "android.support.v4.content.FileProvider" instead of "androidx.core.content.FileProvider" (with the required *.jar library added to the project but it created duplicates with androidx.core).

    I also tried making my own CustomFileProvider class to be referenced by the AndroidManifest.xml file, but fails again.

    I followed many threads, the last of which made me think it may have something to do with how I set Unity publishing settings..?
    https://forum.unity.com/threads/crash-at-app-startup-fatal-exception-main.726650/
    https://discussions.unity.com/t/problem-with-file-provider-class/233959/2

    Whenever I try to add references to the FileProvider via custom AndroidManifest.xml on Unity side, add "dependencies { implement:androidx.core[...] }" and "android.useAndroidX=true", Unity fails to build saying that gradle version is not set for Android SDK > 32.

    A huge thanks to anyone who will take the time to read me, please be sure I'll follow that thread with attention. Best regards. ;)
     
  2. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,948
  3. Stericraft

    Stericraft

    Joined:
    Sep 25, 2020
    Posts:
    6
    Hi Tomas, thanks a lot for your reply, this has been very helpful!

    I added as you said, and then realized Unity wasn't configured to use Jetifier and AndroidX.

    So in addition to adding:
    -keep class androidx.core.content.FileProvider { *; }

    to gradleTemplate.properties, file to enable via Unity->Edit->Projects Settings->Player->Publishing Settings->Custom Gradle Properties Template.

    I also added:
    android.useAndroidX=true
    android.enableJetifier=true

    to gradleTemplate.properties, file to enable via Unity->Edit->Projects Settings->Player->Publishing Settings->Custom Gradle Properties Template.

    Final Android Studio AndroidManifest.xml configuration is:
    <application>
    <provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="[USER=94913]@XML[/USER]/file_paths" />
    </provider>
    </application>


    I let a lot of details on how to access these files for those who would encounter a similar issue.

    New problem
    I now have an issue with configuring the file path to be opened by my plugin. If this requires a new post, I'll remove the following text and open a new thread (let me know).

    Now that the app runs, I get the following error:
    java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.opu.securityconcilapp/files/storage/emulated/0/Android/data/com.opu.securityconcilapp/files/<NAME_OF_APK_FILE>.apk


    My plugin's package name in Android Studio is "com.opu.intranet".
    The name of my final Unity apk is "com.opu.securityconcilapp".

    Here is the file_paths.xml I use in Android Studio for my OpenApkFile() java method:
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--<external-path path="Android/data/com.opu.intranet" name="files_root" />-->
    <!--<external-path path="Android/data/com.opu.securityconcilapp" name="files_root" />
    <external-path path="/data/data/com.opu.securityconcilapp/files" name="files_root" />
    <external-path path="." name="external_storage_root" />-->

    <external-path path="Android/data/com.opu.securityconcilapp" name="files_root" />
    </paths>


    All those I commented were tested and do not work either.
    My file is downloaded by Unity at runtime and stored in "Application.persistentDataPath".

    Any idea how to configure the path properly?
    Should I, maybe, call my plugin's package by the same name as the Unity side app ?

    Thanks again!
     
  4. Tomas1856

    Tomas1856

    Unity Technologies

    Joined:
    Sep 21, 2012
    Posts:
    3,948
    Sorry no idea about this one
     
  5. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,766
  6. Stericraft

    Stericraft

    Joined:
    Sep 25, 2020
    Posts:
    6
    Very useful ressource, I didn't find it during my research, thank you!
    The changes I needed to do to make it work are part of that package, so that will be useful for others. (I found out on my own shortly before your reply).

    For the file_paths.xml entry that was required, it happened that no entry is required on Unity side.
    Here is the final file_paths.xml I now use to allow my Android Studio plugin to access the downloaded file:

    <files-path path="/storage/emulated/0/Android/data/<UNITY_APK_PACKAGE_NAME>/files" name="files_root" />


    This is the path provided to my Android Studio plugin (that has a different name than the Unity package, but requires the Unity Package name because it's this that downloaded the file I try to open in the first place).

    Now (because problems never stop arising :D), it says "Problem occured while analyzing package" when it opens it, even though downloading the APK via my web browser and installing it via the File Manager works fine.
    Probably an authorization issue :( I'll seek an answer to that later and keep showing my findings here!