airsdk / Adobe-Runtime-Support

Report, track and discuss issues in Adobe AIR. Monitored by Adobe - and HARMAN - and maintained by the AIR community.
203 stars 11 forks source link

ANE res folder missing in android since SDK 743 #1790

Open lamselli opened 2 years ago

lamselli commented 2 years ago

I have a Firebase ANE that was working perfectly when built with SDK 686, and it is not working anymore with SDK 743 or 795.

When I unzipped both apks, I notice that in the non working apks, the res folders were missing :

For instance in working apk, I have the file assets/META-INF/AIR/extensions/com.myflashlab.air.extensions.firebase.core/META-INF/ANE/Android-ARM/com.google.android.gms-res/values/com_google_android_gms_values.xml. working_apk

In non working apk, this file is missing. non_working_apk

I think that this missing file is causing my issue... Why are res missing ? I believe this is a bug ?

lamselli commented 2 years ago

@ajwfrost could it be related to this feature #163 ?

ajwfrost commented 2 years ago

Hi

I don't think it's directly related to that other feature; this is more likely happening because of our switch to using Gradle and the standard Android build tools/pipeline to build our APKs (and AABs). This resulted in some changes to how resources within ANEs were being handled/packaged, which needed some updates in the ANEs... so I would suggest looking at pulling down the latest version of these .. although I'm just seeing the fact you're using one from MyFlashLabs... which means you'd be better off switching the APK mechanism back to the old one rather than using Gradle.

So to do this, in your app descriptor file in the <android> section, can you add a line <BuildLegacyAPK>true</BuildLegacyAPK> and see if that helps?

thanks

Andrew

marchbold commented 2 years ago

@lamselli I don't believe this is your issue. Resources were actually incorrectly copied into the assets/META directory in the past and weren't used there, the fact that they are missing from the APK isn't an error but an improvement :)

So unless the developer of your ANE was relying on this error and reading the files directly rather than through the Android resource system, there's probably a separate issue with the extension.

The only minor change we had to make to our extensions was ensuring the package name for the resources was correct. We had one extension (com.distriqt.playservices.Base) that had an incorrect package name and was causing an issue not being able to find the associated resources.

If you post the logs from the failed application I may be able to help further, however the approach Andrew has suggested to use the legacy build system is a decent quick fix.

lamselli commented 2 years ago

Hi @marchbold, thanks for your feeback. I tried with the buildlegacyapk and indeed, the extension works.(And when I unzip the apk, the xml file is back in the same folder).

To be more precise with my issue with this ANE: if I dont use the buildlegacyapk, in debug, I get the fllowing trace : "initFirebase > Firebase configuration json file is missing"

If I use the buildlegacyapk, I get the following trace : [trace] default_web_client_id = 1*.apps.googleusercontent.com [trace] firebase_database_url = https://***.europe-west1.firebasedatabase.app [trace] gcm_defaultSenderId = [trace] google_api_key = [trace] google_app_id = [trace] google_crash_reporting_api_key = [trace] google_storage_bucket = * [trace] project_id = ** [trace] FirebaseAnalytics.init

which is basically the content of the missing xml file.

Since myFlashLabs no longer supports their ANEs, I used Procyon to decompile the java classes.

And I found this piece of code :

private boolean initFirebase(final boolean prepareForDynamicLinks) {
        this.toTrace("command:initFirebase");
        if (this.activity.getApplicationContext().getResources().getString(R.string.firebase_database_url).equals("placeHolder")) {
            this.toTrace("initFirebase > Firebase configuration json file is missing");
            return false;
        }

And the firebase_database_url is once again in my missing xml file.

I could really use some help to make it work again...

@ajwfrost @marchbold Thank you both in advance for your help!

Le lun. 28 mars 2022, 01:37, Michael @.***> a écrit :

@lamselli https://github.com/lamselli I don't believe this is your issue. Resources were actually incorrectly copied into the assets/META directory in the past and weren't used there, the fact that they are missing from the APK isn't an error but an improvement :)

So unless the developer of your ANE was relying on this error and reading the files directly rather than through the Android resource system, there's probably a separate issue with the extension.

The only minor change we had to make to our extensions was ensuring the package name for the resources was correct. We had one extension (com.distriqt.playservices.Base) that had an incorrect package name and was causing an issue not being able to find the associated resources.

If you post the logs from the failed application I may be able to help further, however the approach Andrew has suggested to use the legacy build system is a decent quick fix.

— Reply to this email directly, view it on GitHub https://github.com/airsdk/Adobe-Runtime-Support/issues/1790#issuecomment-1080044990, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABNICXZM7NY5PCGP4Q56OOLVCDWKVANCNFSM5RTZLRFQ . You are receiving this because you were mentioned.Message ID: @.***>

lamselli commented 2 years ago

I also built myself an ANE that was including png file (for notification purpose). In my ANE sources, I have put those png files in my res folder : image

When I build an apk with my ANE, with the buildlegacyapk, I can find the same structure in the assets/META folder : image

However, if I dont the legacy apk, I cant find those png. Where do all the res contents from ANEs end up now ? Am I also doing something wrong with my ANE ?

lamselli commented 2 years ago

I gave antoher try : I used apktool to extract the newly built apk. I can indeed find in values/string.xml my values : <string name="firebase_database_url">https://******.europe-west1.firebasedatabase.app</string>

I dont get why the extension cant access it with the code :

if (this.activity.getApplicationContext().getResources().getString(R.string.firebase_database_url).equals("placeHolder")) {
            this.toTrace("initFirebase > Firebase configuration json file is missing");
            return false;
        }

Do you have any idea ? @marchbold Is it the same issue as the one you had with your extension ?

Thanks again.

ajwfrost commented 2 years ago

What are the values in your platform options? That's meant to provide a link between a package name and a set of resources, so "R.string.xxx" just depends on what context you're running in...

I'll see if I can dig out the details we had on this when it was first encountered...

thanks

lamselli commented 2 years ago

Here is the platform.xml used in the ANE that doesn't work :

<platform xmlns="http://ns.adobe.com/air/extension/29.0">

    <packagedResources>
        <packagedResource>
            <packageName>com.myflashlab.firebase.core</packageName>
            <folderName>com.myflashlab.air.extensions.firebase.core-res</folderName>
        </packagedResource>
        <packagedResource>
            <packageName>com.google.android.gms</packageName>
            <folderName>com.google.android.gms-res</folderName>
        </packagedResource>
    </packagedResources>

</platform>

FYI, I gave a try with my own native extension : I tried to reach for a file using with the code below it didn't work (it even seemed that the code in the ANE was stopping as soon as I call for R.string.* in my code): this.activity.getApplicationContext().getResources().getString(R.string.my_string)

Instead, it works perfectly if I use this way to call my Resources :

this.activity.getApplicationContext().getResources().getString(getResourseIdByName(this.activity.getPackageName(),"string","my_string"))

public static int getResourseIdByName(String packageName, String className, String name)
    {
        int id = 0;
        try 
        {
            for (int i = 0; i < Class.forName(packageName + ".R").getClasses().length; i++)
            {
                if(Class.forName(packageName + ".R").getClasses()[i].getName().split("\\$")[1].equals(className))
                {
                    if(Class.forName(packageName + ".R").getClasses()[i] != null)
                        id = Class.forName(packageName + ".R").getClasses()[i].getField(name).getInt(Class.forName(packageName + ".R").getClasses()[i]);
                    break;
                }
            }
        } 
        catch (Exception e)
        {
            return -1;
        }
        return id;
    }
marchbold commented 2 years ago

Sounds like an issue related to the one I mentioned. i.e. that AIR now correctly places the resources in the package name you specify in the platform.xml, as previously they were in the main application package and duplicated.

Firebase configuration resources need to be in the application package namespace, so instead of trying to package your config resources in an extension, simply add them to the resdir directory you can add directly in air now.

https://airsdk.dev/docs/tutorials/platform/android/custom-resources


On your usage of the R. this R is scoped to your package name, so you must ensure the R reference in your android code matches the package name that you specify in the platform xml. Otherwise they won't match when packaged in the AIR application.

lamselli commented 2 years ago

If I understand correctly what you said, since the XML containing the string value is specified in platform.xml as in com.google.android.gms, the ANE can't access it using R., even if it is packed in the main application package.

In other words, now ANEs can access only a res folder with matching package name as the Android classes in the ANE (or we can use the workaround as described above to access the main application package from the ANE)

Is this correct ? Or the ANE will work again if I put the config resources in the res folder ?

marchbold commented 2 years ago

I'm not exactly sure what your error is, but using the R.* mechanism normally scopes this reference to the library's package name, not the applications. To access the applications you need to do something similar to what you have referenced above.

However I was questioning why you need to do this, if it's just to get firebase config working, you shouldn't need to directly access it from your extension, just place them in your applications resources (resdir) and then firebase will keep them up from there.

lamselli commented 2 years ago

I totally agree with you, if I built the ANE myself, I would now put the resources using the res folder. But this is not an ANE I have created, and I don't have the sources either. (I just did some decompiling to understand how it worked) My goal with this ANE was to use OneSignal SDK. Myflashlab was providing a cloud messaging ANE including OneSignal. But to use it, you also needed to use their firebase core ANE. Unfortunately, from what I understand from the decompiled java files, at init, this ANE is checking if the firebase config files are existing using "R.". And since they don't maintain their ANEs anymore, I think I'll have to find another way to use firebase cloud messaging and OneSignal.

Thanks for your help 🙏

raresn commented 2 years ago

I highligy recomment going with the ANEs from Distriqt. You can't go wrong with them, and the support is brilliant!

lamselli commented 2 years ago

It was my idea ! Either making the ANE myself or using the ones from distriqt 😉