Android Facebook content provider authority - android

I'm developing an app with (at least) two flavors having different package names - therefore actually two different apps as far as the android system is concerned. The app uses Facebook sharing, so I have the provider declared in the manifest:
<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
This is done according to Facebook's instructions: https://developers.facebook.com/docs/sharing/android
This works fine with one app, but trying to install the second app on the same device fails with the error INSTALL_FAILED_CONFLICTING_PROVIDER. This is the only provider defined in the manifest so I'm pretty sure it's the problem. If I change the provider string to be something different it crashes when attempting to open a Facebook share dialog.
I've seen claims that it's possible to use the same Facebook app in multiple android apps, but can't find anything in Facebook's documentation about it. Has anybody done this, and how did you get around the provider authority problem? Thanks.

One of the possible solutions I have found is the one described here
http://gradlewhy.ghost.io/overcoming-install-failed-conflicting-provider/
I am already using this for (debug/release variants) android.support.v4.content.FileProvider and as far I have tested also works for com.facebook.app.FacebookContentProvider.
Just add into apps build.gradle
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
resValue "string", "fb_provider_id", "com.facebook.app.FacebookContentProvider{app_id_1}"
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
resValue "string", "fb_provider_id", "com.facebook.app.FacebookContentProvider{app_id_2}"
}
and then in the AndroidManifest
<provider android:authorities="#string/fb_provider_id"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>

I was able to solve this by having separate manifests for my debug and release flavors and in my debug flavor manifest, I added the snippet for the provider but set the exported value to false. In my release flavor manifest, I have the original provider snippet with exported set to true.
After I did this, I no longer got the INSTALL_FAILED_CONFLICTING_PROVIDER error.
<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="false"/>

<provider android:authorities="com.facebook.app.FacebookContentProvider{app id here}"
android:name="com.facebook.FacebookContentProvider"
android:exported="false"/>
exported can be "true"

If your have one project and multiple flavors(means: multiple apps with minor tweaks) like me, you can
1.create multiple facebook app (from https://developers.facebook.com/apps/)
2.add codes for correspoding flavor
3.add facebook_app_id string value in the corresponding flavor's folder.
Example:
app/build.gradle
...
flavorDimensions "regular"
productFlavors {
flavour_name {
dimension "regular"
resValue "string", "authority", "com.facebook.app.FacebookContentProvider123456789"
}
app/src/main/AndroidManifest.xml
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>
<provider android:authorities="#string/authority"
android:name="com.facebook.FacebookContentProvider"
android:exported="true" />
app/src/flavour_name/res/values/string.xml
<string name="facebook_app_id" translatable="false">123456789</string>

Related

Using a different manifestPlaceholder for nested Flavors

I do have a structure like below. I wanna use different manifestPlaceHolder like this, projectXTest, projectXDev, projectXProd all use different manifestPlaceHolder while projectYTest,Prod,Dev uses the same manifestPlaceHolder. What I can do besides putting that values to string.xml for all different flavors
android {
buildTypes{
debug{
// Some debug setup
}
release{
// Some release setup
}
}
flavorDimensions "project" , "default"
productFlavors {
projectX{
dimension 'project'
}
projectY{
dimension 'project'
}
Test{
dimension 'default'
}
Dev{
dimension 'default'
}
Prod{
dimension 'default'
}
}
}
Since I could find an out of this. I followed this steps. I hope, If somebody find her/himself in this situation, this helps.
Firstly
Put a manifest to desired flavors directory, for my example I've put android manifest to src/projectY and src/projectX
Beware these not to be full manifest. It should be layered like below
<manifest>
<application>
<activity>
android:name=".x.loginActivity"
tools:node="merge" // this is must
// your flavor spesific code
</activity>
</application>
</manifest>
Secondly
Delete your code to minimum in main XML. What i mean that manifest you've created in src/flavor will be merged with main one. so that delete what you want to seperate and leave what you want to used common in main.
Thirdly
Give different manifestPlaceholder name if you need to seperate prod,dev and staging.
For example,
src/projectX/manifest.xml
<activity>
.
.
android:host='${projectXHost}'
.
</activity>
src/projectY/manifest.xml
<activity>
.
.
android:host='${projectYHost}'
.
</activity>
in gradle
productFlavors{
prod {
manifestPlaceholders = [projectXHost : 'xxx' , projectYHost : 'yyy']
}
}
Since this is my first answer, I'm sorry with layout and expressions. I hope you can understand what I mean. Have a good day

Send a chain to the concatenated gradle

Currently I'm sending wanting to send these two variables HOST WS and PORT WS, I've already captured them in the view, but the conflict is that those two chains I want to send them and at the same time concatenate them within the Gradle, exactly in the URL parameter .
The purpose of this is to make my web-service completely configurable when I change my route.
Do you have any idea how to do it? I would like a hand.
Here I configure these two parameters
I want to send it concatenated to my Gradle
To use buildconfig from build.gradle to Android manifest then.
android {
// For settings specific to a product flavor, configure these properties
// for each flavor in the productFlavors block.
defaultConfig {
// Creates a property for the FileProvider authority.
def filesAuthorityValue = applicationId + ".files"
// Creates a placeholder property to use in the manifest.
manifestPlaceholders =
[filesAuthority: filesAuthorityValue]
// Adds a new field for the authority to the BuildConfig class.
buildConfigField("String",
"FILES_AUTHORITY",
"\"${filesAuthorityValue}\"")
}
...
}
...
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${filesAuthority}"
android:exported="false"
android:grantUriPermissions="true">
...
</provider>
</application>
</manifest>

Instant run doesn't work due to "multiple process"

After having configured instant run, the run button has a small yellow thunderbolt.But while I run the app, Android Studio still performed a full build & install, full message is listed in the picture.
I've searched the official documents in http://tools.android.com/tech-docs/instant-run , but there wasn't anything about "multiple process".I wonder "multiple processes" means compiling or my android app.
What should I configure to turn off multiple processes and experience instant run ?
Instant Run is not enabled for your app because it is using multiple processes.
As stated on the Android Tools Project Site (http://tools.android.com/recent/androidstudio20beta6availableinthecanarychannel):
"Apps that were using multiple processes (via android:process in the manifest) were not being updated properly with Instant Run. For the time being, we have turned off Instant Run in such a scenario."
Hence, to experience instant run, you must ensure your app isn't using multiple processes. Check your AndroidManifest.xml for this.
It may be that the multiple process usage comes from an imported library. LeakCanary, for example, uses multiple processes, defined in its own AndroidManifest.xml. The best way to find where this is defined is to search your entire project (Cmd-Shift-F in Android Studio on OS X) for "android:process".
I ran into this problem when running ProcessPhoenix. Instead of disabling it completely, I just disabled it for my debug build.
Instead of compile I use
releaseCompile 'com.jakewharton:process-phoenix:2.0.0'
And to not break the build I use reflection to trigger the application process restart:
try {
Class clazz = Class.forName("com.jakewharton.processphoenix.ProcessPhoenix");
Method triggerRebirthMethod = clazz.getMethod("triggerRebirth", Context.class);
triggerRebirthMethod.invoke(this, new Object[]{getActivity()});
} catch (Exception e) {
// Exception handling
}
So now I can still use Instant Run and keep the lib included. :)
(Of course, reflection is never ideal, but the app process restart is only used in one rare particular case in the app.)
I tried a lot... and quick solution is to remove android:process=":remote" when developing..
but that's not enough.. try bellow.
use Flavors.
build.gradle(app)
buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.debug
}
release {
minifyEnabled true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
development {
minSdkVersion 21
}
production {
minSdkVersion 14
}
}
flavorDimensions "default"
Now you have 4 Build Variants => developmentDebug, developmentRelease, productionDebug, productionRelease
developmentDebug, developmentRelease => no use multi process
productionDebug, productionRelease => use multi process
2. copy orginal "AndroidManifest.xml" to YouAppRoot\app\src\production, and then remove all elements except 'service'.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp"
android:installLocation="auto">
<application
android:name=".App"
android:allowBackup="true"
android:hardwareAccelerated="#bool/gpu_enabled"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:largeHeap="true"
android:theme="#style/MyTheme">
<service
android:name=".xxxx.MyService"
android:exported="false"
android:process=":remote">
<intent-filter>
<action android:name="xxxx.test.aaa" />
</intent-filter>
</service>
</application>
remove android:process=":remote" line from original AndroidManifest.xml
now you can check like below.

Application name as gradle parameter

I want to do something like that: gradle build DemoApp, and have DemoApp.apk with application name "DemoApp" as output.
Also, can I change application icon if with the same flow?
And some inner parameters?
Product flavors - not a secret for me. I do not need different configurations, I need to change application name at the build time. For example, I have some Rest API, that allows to pass parameter and return apk with application named as that parameter. The same with icon and other.
Checkout Manifest Merger specifically placeholders. Below is an example of setting the app name in gradle file.
// AndroidManifest.xml
<application
android:label="${applicationName}"
// build.gradle
buildTypes {
release {
minifyEnabled false
manifestPlaceholders = [applicationName: "MobileWorkforce"]
}
The other option is to use #string/app_name and define different string.xml files based upon buildType/flavor.
Given that you don't know how to use flavours properly, a mix of other solutions.
AndroidManifest.xml
<application
android:label="${applicationName}"
MyHttpThing.java
callserver(BuildConfig.ENDPOINT + "/api/v3/", "stuff")
build.gradle
buildTypes {
release {
minifyEnabled false
manifestPlaceholders = [applicationName: myappname]
buildConfigField "String", "ENDPOINT", myendpoint
}
and call with
gradle -Pmyappname=namy_name_name -Pmyendpoint="http://google.com" build DemoApp
Looks like you're looking for Product Flavors, they're exactly for having multiple customized versions of the app with shared codebase. You can customize the icon, as long as any other resource. And yes, the .apk will be named according to the name of the flavor.

Android: automatically choose debug/release Maps v2 api key?

I'm using Google Maps v2 API in my project. In Google Maps v2 the debug/release API key is defined in AndroidManifest.xml. I have seen the link but in that map key is defined in a xml layout file not in AndroidManifest.xml. So can I define both debug and release keys for my project in AndroidManifest.xml?
I want something like this in AndroidManifest.xml:
If debug mode:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/debug_map_api_key"/>
If release mode:
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/release_map_api_key"/>
Using build.gradle
buildTypes {
debug {
buildConfigField("String", "map_api_key", "\"your debug map api key here\"")
}
release {
buildConfigField("String", "map_api_key", "\"your release map api key here\"")
}
}
I solved this issue using this steps:
In Google Developer API Console
Click on Create New Android key...
In cmd.exe/Terminal: keytool -list -v -keystore mystore.keystore
Password: android
Now enter SHA1 key;package name for debug and press enter
Enter SHA1 key;package name for release
Click on Create
Now use this API key your project
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/common_map_api_key"/>
One of the Best way to use build.gradle file in latest Android 5.0 and Android 6.0, Android 9+ (API 20, 21,22,23, 24, 25,26, 27 28, 29)
Well you can use them simply without creating product flavors in gradle. This is another example we can achieve via Gradle. You can achieve it with two simple steps.
Add custom value to manifestplaceholders build.gradle file.
See below
buildTypes {
debug {
manifestPlaceholders = [ mapApiKeyValue:"GHjaSyAjlyp3O831lgaonHMXsd-_DpQ3002x3S4"]
}
release {
manifestPlaceholders = [ mapApiKeyValue:"AIzaSyAuMGDLr2HeuRed4JA0CrdYYdZRjeC3EA"]
}
}
Edit manifest file like below.
part of my manifest file
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="${mapApiKeyValue}" />
This solution works for the latest Android 5.0 and Android 6.0 (API 20, 21,22,23)
Updated on 5/3/2018 for Xamarin Form and Xamarin Native Apps
Open AssemblyInfo.cs in Android Project and addd the following code
#if DEBUG
[assembly: MetaData("com.google.android.maps.v2.API_KEY", Value = "DebugKey123123123")]
#else
[assembly: MetaData("com.google.android.maps.v2.API_KEY", Value = "ReleaseKey123123123")]
#endif
To Check the AndroidManifest file, goto obj/Debug/android folder and open the manifest file and check the meta info,
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="DebugKey123123123" />
For organizations that need to maintain separate keys, you can place them in separate directories in Android Studio. Make sure the subdirectory of src you use matches a flavor or buildType
From Building Your Project with Gradle:
To build each version of your app, the build system combines source code and resources from:
src/main/ - the main source directory (common to all variants)
src/<buildType>/ - the build type source directory
src/<flavorName>/ - the flavor source directory
In projectroot/yourapp/build.gradle:
buildTypes {
debug {
runProguard false
debuggable true
}
release {
runProguard true
debuggable false
...
}
In projectroot/yourapp/src/main/AndroidManifest.xml:
...
<application
android:name=".MyApplication"
android:theme="#style/Theme">
<!-- Don't put your key here -->
...
In projectroot/yourapp/src/debug/AndroidManifest.xml, fully qualify the name of the app.
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name="com.hipmunk.android.HipmunkApplication">
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="yourdebugkey" />
</application>
</manifest>
In projectroot/yourapp/src/release/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:name="com.hipmunk.android.HipmunkApplication">
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="release key" />
</application>
</manifest>
Since you are using gradle you can do the following:
build.gradle
android {
.. .. ...
buildTypes {
debug {
resValue "string", "google_maps_api_key", "[YOUR DEV KEY]"
}
release {
resValue "string", "google_maps_api_key", "[YOUR PROD KEY]"
}
}
}
And in your AndroidManifest.xml
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_api_key"/>
This way you only have one AndroidManifest.xml and you set value based on your build type. Hope this helps.

Categories

Resources