Currently I'm using twilio to make calls in android in my application but they don't support arm64 phones yet, my application keeps crashing as it doesn't find the appropriate libtwilio-native.so file.
Is there a way to disable this service only for an architecture? Is there a way to disable the service by default and enable it in runtime?
Additional info:
My manifest.xml file has this:
<service
android:name="com.twilio.client.TwilioClientService"
android:exported="false" />
The bools.xml trick doesn't work for me as arm64 phones and others phones can have the same android version.
Is there a way to disable the service by default and enable it in runtime?
Add android:enabled="false" to the <service> in the manifest. Then, at runtime, you can use PackageManager and the awkwardly-named setComponentEnabledSetting() method to enable it, if desired.
The bools.xml trick doesn't work for me as arm64 phones and others phones can have the same android version.
True, though if you are using product flavors in Android Studio for handling your CPU architecture splits, you should be able to use resConfig in the product flavor definitions in Gradle in lieu of the actual bools.xml files to define the boolean resource, and use that in android:enabled. Note that I have not tried this, YMMV, do not taunt Happy Fun Ball, etc.
Related
I ran into one confusing issue today about the security tip on developer.android.com such as
allowbackup
debuggable
according to
this merging logic, I think it will come to application manifest and then library manifest. if now host app overwrite the flags i set in library, does that mean i no longer have protection to my library?
for example,
<manifest //this is library manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MYLIBRARY_MANIFEST"
xmlns:tools="http://schemas.android.com/tools">
<application android:allowBackup="false"
android:label="#string/app_name">
</application>
</manifest>
<manifest //this is application manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.MYAPPLICATION_MANIFEST"
xmlns:tools="http://schemas.android.com/tools">
<application android:allowBackup="true" //overwrite it as true
android:label="#string/app_name">
</application>
</manifest>
Is there a away to protect the library itself by forcing the library not allowbackup or not debuggable?
does that mean i no longer have protection to my library?
Libraries do not really have "protection" in the first place with respect to manifest entries. Users do.
The developer of the app that uses your library can choose what to do for android:allowBackup, android:debuggable, etc. In the specific case of android:debuggable, that is usually set via Gradle: debug builds set it true; release builds set it false.
Is there a away to protect the library itself by forcing the library not allowbackup or not debuggable?
Libraries do not really have "protection" in the first place with respect to manifest entries. Users do.
You cannot prevent developers from setting whatever value they want for those attributes.
You are welcome to examine the ApplicationInfo object for the app (call getApplicationInfo() on any Context) to see what those flags are set to. You are then welcome to take whatever steps you want based upon that information.
However, bear in mind that the step you appear to want to take — prevent the app from running if the developer does not submit to your demands — simply means that your library will not be used. Telling developers that they cannot do debug builds, for example, is not going to be very popular.
You have Host project and Library. I will explain in debuggable example.
Actually host app always will be play a most important role.
If you doesn't include debuggable flag into manifest file in your library, Android get this flag in Host App (if exist).
So when you setup debuggable = false flag in Library and debuggable=true in Host App, this means that you debuggable flag doesn't affect library, but Host app - affected.
Background
In the past, when Eclipse&ADT were the official tools to develop for Android, you could simply use "manifestmerger.enabled=true" inside the "project.properties" of the app's project, and you got it merging all of the libraries' manifests automatically (and I've posted about it here).
This worked, sometimes. It had a lot of weird issues, and I always preferred to just avoid using it, and put what is needed into the main manifest file manually.
The problem
Somewhere on 2014, Google announced that the new Android-Studio (0.1 I think), together with Gradle, will allow you to choose exactly how to perform merging of libraries' components.
However, the new instructions (link here) are very complex and I really (really) tried to understand how to use them, and also didn't find samples of how to use them.
It's not that I didn't understand anything, but I'm not sure if I understood well.
What I've found
On the bright side, I've found out that merging is done completely automatically, so if you have a BroadcastReceiver on the library's manifest (and as a class, of course), it will be added to the app's project that uses it.
The question
I can't simply ask everything to be explained. I think it will be enough to ask those questions:
How can I choose which app components (permissions, activities,...) to be ignored from being auto-merged?
How can I point override app components (of the library) attributes (on the app's project) ? for example the theme of the activities?
Is there a way to completely disable the auto-merger for the manifest files?
What happens with manifests of dependencies that are inside repositories? Are they merged too?
Are there any tutorials/samples/videos regarding this new (well new for me) feature?
Are there any things I should be aware of when using the auto-merger?
I hope those questions are representative enough, informative enough, yet not too hard to answer for people who know.
1. Disabling elements
You can always explicitly disable permissions and features in your app's manifest and override any library values. And i found that you can disable elements from library.
Example
Consider the following code from the above link:
<activity-alias android:name="foo.bar.alias">
<meta-data
android:name="zoo"
tools:node="remove" />
</activity-alias>
By having this code inside your manifest you ensure that the merger finds any <activity-alias> elements with android:name="foo.bar.alias" attribute and removes a <meta-data> element if it has the android:name="zoo" attribute. It removes just the "zoo" meta data. Not the activity alias. If you specify this in your main manifest it will be effective on anything that has been merged so far (elements from libraries).
Example #2
Since you requested an example with activities, this is what I've come up with:
<activity android:name="com.example.ui.MyActivity" tools:node="remove" />
This line will make the merger remove any activities with android:name="com.example.ui.MyActivity" attribute that have been merged so far. So if you specify this in your main manifest it will effectively remove any com.example.ui.MyActivity entries that might have been merged from libraries.
2. Overriding attributes from library
The order in which the values are merged are described here. Basically, it goes like this: libraries, then main manifest, then flavors and build types manifests if you use those.
What are build types?
The default are "debug" and "release". You can define your own and override settings like signing or proguard. For your purposes you could say it's the equivalent of run configurations.
It works like this: you put your default and shared values inside the main manifest. Then in flavor manifests you override the values you need. Google "gradle flavors" for more info.
The following example is taken from a previous version of manifest merger documentation.
Override an attribute coming from a library
Using tools:replace="x, y, z" will override x,y,z attributes from the
imported library’s activity XML declarations.
Higher Priority declaration
<activity
android:name="com.foo.bar.ActivityOne"
android:screenOrientation="portrait"
android:theme="#theme1"
tools:replace="theme"/>
with a lower priority declaration :
<activity
android:name="com.foo.bar.ActivityOne"
android:theme="#olddogtheme"
android:windowSoftInputMode="stateUnchanged"
android:exported="true">
will result in :
<activity
android:name="com.foo.bar.ActivityOne"
android:screenOrientation="portrait"
android:theme="#theme1"
android:windowSoftInputMode="stateUnchanged"
android:exported="true"/>
3. Disabling manifest merger altogether
See Disable Manifest Merger in Android Gradle Build.
android.applicationVariants.all { variant ->
variant.processResources.manifestFile = file('src/main/AndroidManifest.xml')
variant.processManifest.enabled=false
}
In what file do you put this?
At the end of your module's (not root project) build.gradle.
4. Are manifests from dependencies merged?
Yes they are (they're libraries).
Is there a way to block merging certain library manifests?
Not that I know of, sorry.
5. Any tutorials?
Depends on what are you trying to achive. So far it always worked for me out-of-the-box.
e.g. http://www.myandroidsolutions.com/2014/04/10/android-gradle-manifest-merge/
The manifest merger documentation (link below).
I don't know about any videos.
6. Anything I should be aware of?
You can check the generated manifest if you get suspicious about extra permissions etc. It's located in project/module/build/intermediates/manifests/full/[flavor]/build-type/AndroidManifest.xml.
Source: https://developer.android.com/studio/build/manifest-merge
Some of the links in this thread are obsolete. Here's the main one that is updated related to auto merger of manifests, by gradle, for Android AARs.
https://developer.android.com/studio/build/manifest-merge
I have a game and it runs well on Android through an application called C4Droid (If you don't know about C4Droid, just google it). It is written in C++ and only uses SDL2.
It runs on portrait and so, when I tilt the device with auto-rotation turned on, it gets landscape.
Now, what I wanted is to do something that avoids it to get landscape even when auto-rotation is turned on. Answer please?
Set orientation in Manifist file like this android:screenOrientation
<activity
android:name="com.androidgames.mreater.MrEaterGame"
android:label="Mr. Eater"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
No, there is no way to do this in SDL2 only (you can in iOS, but for some reason they made it different in Android). wadali's answer is best, here are some ways you can use it in your build environment:
Use a different build environment. If you build the APK on a desktop machine you can control the contents of the AndroidManifest.xml file. If you really want to do it on your phone, there are other C/C++ compilers for Android. The part you lose is C4Droid's ease of use - you will need to learn how to build the APK yourself.
Build it using C4Droid as usual, and then use an APK editor to extract, edit, and repackage AndroidManifest.xml. If you're comfortable copying the APK to a desktop machine you can use apktool to unpack the APK, edit the file you need, then repack it again (note: you will need to re-sign the APK after doing this before it can be used); otherwise, there seem to be a few APK editor utilities available for Android, too.
There are Android APIs for controlling the orientation, but you can't access them from within SDL2. SDL2 creates its own Activity and doesn't have any means of either extending it or letting you provide your own activity, so you cannot expose additional Android API calls to your own code.
Do you know about SDL_HINT_ORIENTATIONS?
https://wiki.libsdl.org/SDL_HINT_ORIENTATIONS
even if SDL docs claim they are for iOS they seem to work fine in Android.
SDL_SetHint(SDL_HINT_ORIENTATIONS, "Portrait");
Is it possible to set values in AndroidManifest.xml by code?
For example I want to set android:largeHeap="true", but it is possible only in 3.x platforms; but my application must run on 2.2 and above.
Then I want to set android:largeHeap="true" on 3.x platforms and do nothing on 2.x platforms by code.
Any ideas??
It is NOT possible to change Manifest at runtime..
from developer.android.com :
The manifest presents essential information about the application to
the Android system, information the system must have before it can run
any of the application's code.
plus:
These declarations let the Android system know what the components are
and under what conditions they can be launched.
so everything is specified before running and then your App runs, under permissions and conditions Android system gave to it.
cheers
I have an app to release which works on all android screen-sizes (except smaller) and densities above SDK version 2.0.
It will also run on extra large screens.
Currently I have added this:
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="false"
android:anyDensity="true"
/>
But I also need to add android:xlargeScreens="true" , to allow it visible in android market on extra large screen devices, since by default it is false.
But to add android:xlargeScreens I need to change my eclipse targetsettings to 2.3 as this attribute was added from API level 9.
So what should I do with my target compilation settings for this scenario ? Should it be 2.3 while compiling ? If yes, then will the app not give any problems while running on devices with 2.0 version ?
Yes you need to change the uses sdk to 2.3 but make sure that you are not using any newer apis which are not in 2.0 or whatever your minimum supported sdk version is. Or in case you want to use them you have to use reflection.
But more about how to use the sdk versions is here and more about uses-sdk is here.
I do the same in my application and make sure you test your application in both[all] the versions before you release.
Best,
Achie.
I'm moving this from the comments to make it more clear for others looking at this question in the future.
When supporting both old and new versions of Android it can be confusing how applications manage to run despite many things change with in the frameworks during each new release, I'm going to try and clarify this here.
An application written for the 1.5 sdk can only call functions that exist for that API level, so for instance the multi touch api's didn't exist in 1.5 and never will. Now you say "Ok but I don't need to call any newer APIs, I just want my app to work in 2.3 and have a2sd support" And I say "Ok, just change your targetApi in the manifest, set the minSDK and compile against 2.3 and you're good to go."
Now why does that work? What if the onMeasure() method for ListView was changed in 2.2 and now calls betterCalculateFunction() within onMeasure()? Why does my app still work?
This is the advantage of late binding in Java. You see, Java is never compiled until it reaches a device and is running, what you are doing in Eclipse is converting it to byte code which contains a bunch of byte code instructions that are later interpreted by the device. The byte code will NEVER contain a reference to betterCalculateFunction() though (unless you directly call it. Calling onMeasure() is indirect). This can happen because when your code is running on the device it gets linked against the Android framework on the device and your code calls onMeasure() directly because it is a public outward facing API. The path of execution will then enter the framework and call whatever it needs to, then once its done return to your code.
So on 1.5 you might see
doStuff (your code) -> onMeasure
(public API) -> done
and 2.2
doStuff (your code) -> onMeasure
(public API) ->
betterCalculateFunction (private
function) ->done
Now if you need to call functions that may or may not exist depending on API level then I suggest you look at a related answer of mine here stackoverflow: gracefully downgrade your app
Hope that clears some things up.
I haven't tried 2.3, but that's what I do with 2.2.
I compile for 2.2 and test on 1.6 to make sure everything works how I'm expecting. I haven't run in to any issues with it.
To double check, set your target for 2.3 and then setup an emulator for a lower rev version to make sure it all works.
The default value for android:xlargeScreens is true, so you don't have to change anything - it's on by default, as long as your minSdkVersion or targetSdkVersion is higher than 4.
http://developer.android.com/guide/topics/manifest/supports-screens-element.html
Here is an official Android developer blog explanation of how this works:
http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html
In summary: you can use the newest XML whilst still supporting the older OS versions in a back compatible way.
While reading this blog post I guess I have an answer on my old question. An extract below (which is for another manifest attribute "requiresSmallestWidthDp" introduced from 3.2):
"The catch is that you must compile your application against Android 3.2 or higher in order to use the requiresSmallestWidthDp attribute. Older versions don’t understand this attribute and will raise a compile-time error. The safest thing to do is develop your app against the platform that matches the API level you’ve set for minSdkVersion. When you’re making final preparations to build your release candidate, change the build target to Android 3.2 and add the requiresSmallestWidthDp attribute. Android versions older than 3.2 simply ignore that XML attribute, so there’s no risk of a runtime failure."
For different screens you have to create multiple apk then it reduces size of your application.In each application's manifest you have to define according to following link.
http://developer.android.com/guide/practices/screens-distribution.html