Including an AAR file conditionally - android

I am using the Estimote SDK, which is included into my project as an AAR file.
I want to use the SDK on devices which support Bluetooth LE, but also want to allow users who do not have supported hardware to install.
The manifest of the Estimote SDK includes:
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
and this prevents the App from installing on a lot of devices.
I can overrule the android:minSdkVersion:
<uses-sdk android:minSdkVersion="18" />
with
<uses-sdk tools:overrideLibrary="com.estimote.sdk" />
but I don't know how to overrule e.g. the bluetooth_le directive.
I tried unzipping the 'aar', changing the Manifest and repacking as a zip with .aar extension, but I get:
Error:Execution failed for task ':idoms-android:processIDomsAndroidDevDebugManifest'.
> com.android.manifmerger.ManifestMerger2$MergeFailureException: java.io.FileNotFoundException: /Users/Luuk/Documents/Java/idoms-android/idoms-android/build/intermediates/exploded-aar/estimote-sdk-preview/AndroidManifest.xml (No such file or directory)
even thought the file is there. Any help would be appreciated!

#Luuk
I'm a author of Estimote Android SDK.
We will be changing <uses-feature android:name="android.hardware.bluetooth_le"> to required=false for the next SDK release .

You should consider creating 2 flavors of your apk, one that has the BLE support and that includes the SDK that you want to use, and another one that doesn't support BLE.
If you create two flavors of your app, let's call them "ble" and "normal", then you are able to declare some flavor-specific dependencies using bleCompile 'yourDependency' and normalCompile 'yourDependency' in your Gradle build file.

Related

Running Xamarin.Forms App on Different Devices [Error: install_failed_missing_shared_library]

I am currently working on a Xamarin.Forms application that uses native barcode scanning capabilities of the mobile device. I have integrated two different device SDKS from different manufacturers (Casio & Denso).
The main launcer is SplashActivity, which shows the splash screen, detects device info and launces one of the following:
CasioActivity
DensoActivity
These activities are responsible for subscribing to scan events raised by corresponding device.
Denso integration is done with a DLL file supplied by the manufacturer, while Casio integration is done through a Xamarin Bindings project, following this tutorial.
Deployment to Casio works fine but when I deploy the application on the Denso unit, I get the following error message in Visual Studio:
install_failed_missing_shared_library device.sdk is required
I believe that the Casio SDK (*.aar file) is forcing that the app runs only on Casio devices. I tried adding the following to the application manifest:
<uses-library android:name="device.sdk" android:required="false" />
and also tried adding the UsesLibrary attribute to all activities to make device.sdk optional but none worked. It appears that the bindings project is injecting the following to the manifest file on deployment:
<uses-library android:name="device.sdk" android:required="true" />
Is there any way to prevent the injection of the above line into the manifest file?
I would like to make the application compatible with both of these units.
I solved this by modifying the aar file.
Use 7zip to extract the aar file to a folder
Find the application manifest in the extracted folder
Set android:required attribute to false.
Zip the folder again
Change the file extension from .zip to .aar
Put the new file under Jars folder as shown here

How to find source of a permission in Unity Android

Note: This question is specific to Unity3D
I have a very clean android manifest file in Unity project under Plugins/Android/ folder with no <uses-permissions/> tag at all. I believe that some permissions in final APK comes from Android Player Settings for-example READ_EXTERNAL_STORAGE. In my Gear VR project I see following lines added in final manifest which can be accessed in Temp/StagingArea/:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
Now this is definitely coming from one of the plugins that I have in my project (I have many plugins).
My app is getting rejected from Oculus saying
Your app is asking for excessive user permissions for using user
permissions inappropriately.
I found a workaround here, but I dont want to do such a thing as this may result in app rejection once again.
So
Is there a way I can find out that where this permission is coming from?
How to find out if there is some code in my scripts which causes unity to include this permission?
Thanks
Easy Way
I think this easier approach applies if your Unity project is being built with gradle. If it isn't, here is one more reason to upgrade.
Also, a big shout-out to an article called, Hey, Where Did These Permissions Come From?)
Build Your Project
Open the file /path/to/my/project/Temp/gradleOut/build/outputs/logs/manifest-merger-release-report.txt
Profit!
Search the file for the name of your permission, and it'll show you where it came from.
Here is part of the file, where I'm looking for the WRITE_EXTERNAL_STORAGE permission.
uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
ADDED from /Users/clinton/Projects/<<ProjectName>>/Temp/gradleOut/src/main/AndroidManifest.xml:7:3-79
MERGED from [gradleOut:IronSource:unspecified] /Users/clinton/Projects/<<ProjectName>>/Temp/gradleOut/IronSource/build/intermediates/bundles/default/AndroidManifest.xml:13:5-81
android:name
ADDED from /Users/clinton/Projects/<<ProjectName>>/Temp/gradleOut/src/main/AndroidManifest.xml:7:20-76
Hard Way
There are three ways permissions get added to your project.
They are specified in an Android Manifest file.
They are specified in library (a .aar file).
Unity adds the permission when you use a certain feature. (Added)
My examples use command-line tools on a Mac. I don't know Windows equivalents, but it is possible to find and run unix tools there (using the linux subsystem for windows 10, cygwin, custom binaries, etc.)
1. Find all permissions used in (uncompressed) Android Manifests.
cd /path/to/my/project/Assets
grep -r "uses-permission" --include "AndroidManifest.xml" .
This will find all files named AndroidManifest in the current folder (.) or any of its subfolders (-r tells it to search recursively) and spit out any line with the words 'uses-permission'.
In my current project, I get output something like this:
./Plugins/Android/AndroidManifest.xml: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
./Plugins/Android/AndroidManifest.xml: <uses-permission android:name="android.permission.INTERNET" />
./Plugins/Android/AndroidManifest.xml: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
./Plugins/Android/AndroidManifest.xml: <uses-permission
./Plugins/Android/IronSource/AndroidManifest.xml: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
./Plugins/Android/IronSource/AndroidManifest.xml: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2. Find the permissions required in Android Libraries
Your project likely contains android libraries (.aar files) and java archives (.jar files). Some android libraries contain an android manifest and specify permissions needed to use the library. (I don't think .jar files actually do this, but .aar files absolutely do). Both .aar and .jar files are .zip files, with a different extension and with specific metadata in specific places.
Find them by running:
find . -iname "*.?ar" -print -exec zipgrep "uses-permission" "{}" "AndroidManifest.xml" ";" 2> /dev/null
Here's what this does.
It finds any file (in the current folder (.) and its subfolders) has an extension of (something) a r, thus .jar, or .aar (-name "*.?ar").
It outputs the archive's file name (-print).
It then runs zipgrep (-exec).
Zipgrep is told to search through any files in the archive ({}) named "AndroidManifest.xml", and output any line with the words "uses-permission".
We then pipe the errors to the bit bucket (2> /dev/null) so we don't see lots of errors about archives that don't have android manifests in them.
An example output looks like this:
./OneSignal/Platforms/Android/onesignal-unity.aar
AndroidManifest.xml: <uses-permission android:name="android.permission.INTERNET" />
AndroidManifest.xml: <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
AndroidManifest.xml: <uses-permission android:name="android.permission.WAKE_LOCK" />
AndroidManifest.xml: <uses-permission android:name="android.permission.VIBRATE" />
...
./Plugins/Android/android.arch.core.common-1.1.0.jar
./Plugins/Android/android.arch.core.runtime-1.1.0.aar
./Plugins/Android/android.arch.lifecycle.common-1.1.0.jar
...
./Plugins/Android/com.google.android.gms.play-services-gcm-11.8.0.aar
AndroidManifest.xml: <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
AndroidManifest.xml: <uses-permission android:name="android.permission.INTERNET" />
./Plugins/Android/com.google.android.gms.play-services-gcm-license-11.8.0.aar
./Plugins/Android/com.google.android.gms.play-services-iid-11.8.0.aar
AndroidManifest.xml: <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
AndroidManifest.xml: <uses-permission android:name="android.permission.INTERNET" />
./Plugins/Android/com.google.android.gms.play-services-iid-license-11.8.0.aar
...
The filenames all start with periods. I can thus see, for example, that the onesignal-unity.aar sets several permissions, several .jar files were searched with no permissions inside them, and some of the play services libraries specify permissions.
If I needed to change a library, I could rename the .aar to .zip, extract it, edit it, compress it, and rename it back. (It isn't necessarily wise to change the permissions inside a library, but possible.)
3. Unity Adds the Permission
I didn't have anything to add on this; as said above, if you use the Microphone API, Unity will add a permission for you so your app will work.
However, I've since realized that you can do the following:
bring up the Build Settings for Android
tick the 'Export Project' box
Export the project, noting the location
go to /my/project/export/src/main/AndroidManifest.xml. This is what Unity emits for the android manifest (before google's tools do all the merging).
compare it (using your favourite diff tool) to Assets/plugins/Android/AndroidManifest.xml; the differences come from Unity.
Unity will add permissions for you on the fly during build time as mentioned by eriQue of Unity Technologies this is to prevent malfunction of code, and unexpected behaviours.
You could use a tool such as this Apk-decompiler to take a look at your new manifest, and which permissions this uses. Based on that you may look for certain functions that could trigger these permissions.
Certain functions such as isGeniune will require several permissions as it will use verification against an external server.
Alternatively you can also replace your manifest in the decompiled APK, manually change out the manifest with the one intended, and resign it. This is some more grunt work, but if proper error logging is in place it might speed up the process of tracking down the problematic functions.
Update
As I mentioned in the comments below as well. There is no real way to pinpoint functions. But a quick check list can not hurt, but will require some work
Are you using any external services?
A lot of external services, think of google, twitter, facebook api's and tools require additional permissions. Usually these are storage/network related, but depending on the goals of the tool / api, it could be many more.
Try building your APK with and without the tools/apis to see if there are any differences.
Are you using unity ads?
Unity ads makes use of 3 permissions by itself, and older versions might still even make use of 5. If you are using their ads, then you will have to take these for granted.
Did you disable unity statistics?
Ever looked at those fancy stats Unity seems to be able to provide? Well, unless you disabled this, you are most likely participating in this as well.
These stats require several permissions, as the phone will be analysed on a hardware level as well as seen in the provided stats.
Are you really using all your api/tool/assets requirements?
You might have included some api's, tools or just about any dll from an external party that may or may not include code that requires dependencies. Just as often those are not 100% sanitized, and might include permission requirements not relevant to their functionality, or to the functionality that you require.
Say, some ad service might want to access a users microphone. But as you are not using their "OMG vocal response analyses" functions, this permission is not required for you.
These permissions can either be removed manually, as I earlier described in my answer. Or through some form of automation such as the post build marked editor script.
QUESTION SPECIFIC:
RECORD_AUDIO permission makes its way into android manifest file if there is a call to Microphone library in any of script in project. It doesn't matter if the script exists in scene or not. In this specific case, if Oculus Platform SDK is imported in project (which is a store requirement) there are few scripts which uses Microphone library. So if you don't use any audio recording feature e.g voice input, just remove the following files under OculusPlatform/Scripts: MicrophoneInput.cs, IMicrophone.cs, MicrophoneInputNative.cs
#mx-d is right. I just want to add another way of fixing this: in build settings you can tick the Google Android Project which will generate an Android Studio project. From there you can use Android Studio's manifest merger tool to override the permissions.
Question #1: the only way to find which library is throwing in the extra permission is to remove libraries one by one, building the project and checking the .apk manifest. Unfortunately unity is not as flexible as Android Studio production-wise.
Question #2: You can not add permissions in Unity through code (unless it's a custom editor script specifically designed for stitching up manifest files)
I found with Unity 2021 the path is now:
/Library/Bee/Android/Prj/IL2CPP/Gradle/launcher/build/outputs/logs/manifest-merger-release-report.txt

Visual Studio Cordova App add plugin as optional feature

I am having an issue in publishing my app in Google play when I include some plugins like cordova-plugin-geolocation in my app, as it adds the following 2 permissions in my manifest file
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
this causes an issue that some of the phones are not able to view the app in the google play as they tell me that android.hardware.location.network access is not compatible on those devices.
when I researched a bit more, I can see that this can be avoided by converting uses-permission to uses-feature and setting the android:required="false" then I can handle it in my code as this is not a must have feature for me.
My issue is I am unable to find how to change this in my visual studio project. can someone please help me understand whats the way to fix this?
Regards
Kiran
There is no way within VS to add contents to your Android projects manifest file. You will have to hand edit those, but beware that these changes would be over-written every time you build your project through VS. There are couple of ways you can workaround this -
You can add post_build Cordova hook that would update the Manifest file.
You can add a gulp task and hook this to MSBuild post_build event through VS.
SOak
(PM - Microsoft)

Import Unity Ads SDK in Android Studio

I just finished an app for Android and I would like to integrate ads on it with Unity Ads. I have to import the Unity Ads SDK project so, I went to : File/Import Module. Once done I entered the path of the folder but after that, I am blocked : Android Studio shows me that :
What should I fill ?
A newer solution:
Go to File > New > New Module > Import .JAR / .AAR package
Select your .aar file (already inside /app/libs dir)
Add this gradle's app dependency: implementation project(path: ':unity-ads')
Now you are ready to use the SDK.
I found solution.
Download and unzip master zip
Go Android Studio File --> Open Module Settings --> click plus button.
When dialog open, you should choose Eclipse project module.
Select unity-ads package in master project.
And Finish.
Stay happy to code :)
I have never tried to import Unity Ads to an non Unity project.
I found this in the Unity website I hope it can be helpful but it's for eclipse...
https://unityads.unity3d.com/help/Documentation%20for%20Publishers/Integration-Guide-for-Android
To answer your question. You shouldn't need to put anything there. It's only if you want to be able to view the source of the library - intelli-sense. That being said, I didn't like that set up and went a different route which I found easier.
Here's what I did.
Download and unzip the master zip (pre-built packages)
Copy or move the ./unity-ads-sdk-master/unity-ads/libs/unity-ads.jar to your projects ./libs dir.
Copy the permissions and Activity definition from the provided AndroidManifest.xml file.
<application>
<activity
android:name="com.unity3d.ads.android.view.UnityAdsFullscreenActivity"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:hardwareAccelerated="true" />
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- Note: If android:maxSdkVersion attribute leads to problems when merging manifests, you can
remove maxSdkVersion attribute. Unity Ads on Android 4.4 or later won't need this permission so
maxSdkVersion means it is only requested for older Androids. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />
3a. Might need to refresh from your Gradle tool window.
Follow rest of instructions starting from Integrate Unity Ads to Your Codebase

<uses-library /> in Android Manifest

I'm a newbie for Android and I need help regarding this issue. I am developing a game using Eclipse. In my project, I added AndEngine and AndEngine Augmented Reality as libraries. I was testing the project out in my Android device, every time I tap the text which uses the class of AR, it force close. I was told to register AndEngine in my Android Manifest file. I have checked about it and used <uses-library />. Now, I placed these two lines in my manifest:
<uses-library android:name="org.andengine.extension.augmentedreality"
android:required="true"/>
<uses-library android:name="org.andengine"
android:required="true"/>
but I get this error message: Installation error: INSTALL_FAILED_MISSING_SHARED_LIBRARY
when I comment out those <uses-library /> lines, I can run the app but it force close when tapping the text that directs to the class of AR. Anything wrong in using it? Or any better way in doing it? Please post all your advises in an easy-to-understand-for-newbies way. THANK YOU!
<uses-library> is not meant to include libraries in your application. It is used to restrict app availability in Google Play based on the availability of a library already on the device like maps. AndEngine is a library project so include it in your build via Ant, Maven or whatever IDE you use.
In case you aren't familiar with what a library project is here's a link:
https://www.vogella.com/tutorials/AndroidLibraryProjects/article.html
If this element is present and its android:required attribute is set
to true, the PackageManager framework won't let the user install the
application unless the library is present on the user's device.
<uses-library> - specifies a shared library that the application must be linked against. This element tells the system to include the library's code in the class loader for the package.
creat a libs folder inside the res folder and put the AndEngine jars in it.set the class path of jar.

Categories

Resources