hyperledger-archives / aries-mobile-agent-xamarin

Apache License 2.0
39 stars 31 forks source link

Android app rejected: Issue: Need to use Media Store API or No Access to Files #53

Closed x0axz closed 2 years ago

x0axz commented 2 years ago

I was trying to upload my app to Google Play Store, but they weren't allowing me to publish it.

Your app currently targets API level 29 and must target at least API level 30 to ensure it is built on the latest APIs optimized for security and performance. Change your app's target API level to at least 30. 

Changes in Manifest File

I then removed these permissions from Manifest File.

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

GetExternalFilesDirs()

And also used to GetExternalFilesDirs() to create folder, as per android documentation

Starting in Android 11, apps cannot create their own app-specific directory on external storage. To access the directory that the system provides for your app, call getExternalFilesDirs().

So, I changed in code:

Path.Combine(FileSystem.CacheDirectory, config.Value); to Path.Combine(Android.App.Application.Context.GetExternalFilesDir(FileSystem.CacheDirectory).AbsolutePath, config.Value);

Run time Permissions to Read & Write

When I removed Read & Write Permissions from Manifest file, I couldn't create folder, I enabled the run time permissions, without adding Read & Write permissions in manifest file, now I'm able to create folder.

await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);
await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);

Changes in MainActivity.cs

I also used GetExternalFilesDir in MainActivity.cs.

var host = App.BuildHost(typeof(PlatformModule).Assembly)
.UseContentRoot(Android.App.Application.Context.GetExternalFilesDir(System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal)).AbsolutePath).Build();  // Android requires that we set content root.

And according to this comment:

var version = CrossDeviceInfo.Current.Version;

if (int.Parse(version) >= 11)
{
    Android.Systems.Os.Setenv("EXTERNAL_STORAGE", GetExternalFilesDir(null).AbsolutePath, true);
}

Action Required: Your app is not compliant with Google Play Policies

After all these changes, I'm unable to publish app on Play store. Received an email:

Issue: Need to use Media Store API or No Access to Files

You have requested access to All Files Access permission but it appears that your app's core feature requires access to only Media Files or does not need access to any Files. In case your app needs access to Media Files, with the MediaStore API, apps can contribute and access media that's available on an external storage volume without the need for the access all files permission.

Please update your app so that the feature uses Media Store APIs and remove All Files Access (MANAGE_EXTERNAL_STORAGE) permission.

horationunez commented 2 years ago

@x0axz taking a look at the issue.

mujeebkalwar commented 2 years ago

I’m facing similar issue

badverybadboy commented 2 years ago

Hi @horationunez. This is a major issue as no one is able to upload their app to the play store. Any idea why this could be happening? Has anyone been able to upload an aries .net app since Nov or Dec ?

x0axz commented 2 years ago

@horationunez any update on this issue?

horationunez commented 2 years ago

@x0axz I'm working out a fix. Can use some help with testing. Is this something you can help out with?

x0axz commented 2 years ago

@horationunez yes, of course. anything you ask for.

Actually I had a chat with @conanoc on Hyperledger Chat. Thread.

Basically, he told not to use GetExternalFilesDir and instead use GetFolderPath. https://docs.microsoft.com/en-us/xamarin/android/platform/files/.

But on android 11, it gave an IO Exception on Pool Creation.

horationunez commented 2 years ago

Yeah, the pool creation error is what gives it away.

horationunez commented 2 years ago

@x0axz I think part of the issue is that these Store rules aren't applied evenly in all versions and the solution to be place in AriesMax repo needs to solve the problem in all of them.

My day is filled today, but will appreciate if I can connect with you tomorrow on a sync call. Feel free to use this link: https://calendly.com/merthin/ariesmax?back=1&month=2022-01

x0axz commented 2 years ago

I removed the WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions from the project's AndroidMainfest.xml and AssemblyInfo.cs files.

I uploaded the .apk to Play Store and in the Bundle permissions the Write & Read permissions were showing up.

Then I analyzed the .apk using Analyze APK feature in Android Studio, and in that, AndroidMainfest.xml has WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE.

Though, I ask for CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage) on run time, but when I removed it and Analyzed the APK, still it includes WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions in Manifest file.

I then add the android:requiredFeature="false" flag to Read & Write permissions like this:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:requiredFeature="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:requiredFeature="false" />

And when I Analyzed the APK again, Write & Read permissions are there with android:requiredFeature="false". But on Play Store, in the Bundle permissions they are there as before.

x0axz commented 2 years ago

@horationunez pointed out that the Permissions somehow merging from the dependent library.

I looked into it and found this article How Libraries can silently add permissions to your Android App and the Fix.

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove" />

It Worked.

But I'm using camera, and I was storing these pictures in the Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData). Which requires WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE permissions.

So, I replace the path with FileSystem.CacheDirectory and it worked (Internal Storage doesn't requires Read and Write Permissions in Manifest file).

x0axz commented 2 years ago

After doing these changes our app get rejected on google play store again, saying: Rejected: Your app is not compliant with Google Play Policies Issue: Not a core feature Issue: Access to device storage not required

Found this Solution, basically saying that Google was checking old APK, if it is available in any of the track (Internal, Open, Closed or Production) with Policy Violation. So, in this regard you have to roll out the app to 100% in the track which has this Policy violation. Which will deactivate the old build.