Android Gradle Build Variant Deploy - android

I just finished setting up build variants with Gradle in Android Studio. What a blessing this will be for a typical demo/pro setup. I'm able to launch my 'demoDebug' app perfectly fine. When I switch to 'proDebug' and 'Run" with the same configuration it installs the pro app fine but crashes launching it:
Starting: Intent { act=android.intent.action.MAIN
cat=[android.intent.category.LAUNCHER]
cmp=com.anthonymandra.rawdroidpro/com.anthonymandra.rawdroid.RawDroid
} Error type 3 Error: Activity class
{com.anthonymandra.rawdroidpro/com.anthonymandra.rawdroid.RawDroid}
does not exist.
If I then go to the dashboard I can launch the pro version and it works as expected. So the install works for the appropriate version; there's only something wrong in the launch (on pro).
build.gradle flavors:
productFlavors {
demo {
packageName "com.anthonymandra.rawdroid"
}
pro {
packageName "com.anthonymandra.rawdroidpro"
}
proAmazon {
packageName "com.anthonymandra.rawdroidpro"
}
}
Update
cleaned up extraneous info unrelated to the issue
When I decompiled the apk I confirmed that none of the gradle overrides were being implemented in the Android.manifest.

First you should have packagename in manner like (recommended approach not mandatory ):
youractualapplicationpackage.flavorname
But you can have packagname whatever you want for flavours like in your case:
productFlavors {
demo {
packageName "com.anthonymandra.rawdroiddemo"
}
pro {
packageName "com.anthonymandra.rawdroidpro"
}
proAmazon {
packageName "com.anthonymandra.rawdroidpro"
}
}
make sure com.anthonymandra.rawdroid is the application's java package inside your main/java directory.
Your AndroidManifest.xml should be like this(Only inside main directory):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.anthonymandra.rawdroid" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".RawDroid"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="#string/app_name"
android:theme="#style/GalleryTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And it should be only in the main directory not anywhere else.
At compilation time gradle will do the necessary package name changes and will make the build.
Same worked fine in my machine and I was able to see two different apps in my device for two different flavors.

The issue was:
'manifestmerger.enabled=false'.
I disabled the function a while back because it caused issues with a library. In the meantime I forgot about it, but apparently the library merging also applies to the gradle merging. I suppose that makes some sense but they really need to allow for separation between gradle merging and library merging.
Thanks to #pyus13 for nonstop support till I came to the typical "Oh s---, are you kidding me..."

Related

Gluon Charm Down Barcode Scanner - Intent handler not found

I am using Netbeans 8.1 and the gluonhq jfxplugin 2.2.0.
I am trying to read a barcode, and created a new project (the standard hello world). I changed the button handler to call a function UpdateText() (below) which in turn calls the Charm Down Scan service.
When I run the app, and click on the button I get the following error in the Android Device Manager:
E/AndroidRuntime(3583): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.gluonhq.charm.down.android.scan.SCAN cat=[android.intent.category.DEFAULT] flg=0x4080000 }
This crash is happening on the scanservice.scan() line.
Button click handler code:
protected void UpdateText(Label label) {
ScanService scanService = PlatformFactory.getPlatform().getScanService();
StringProperty scannedString = scanService.scan();
scannedString.addListener((obs, ov, nv) -> System.out.println("Scanned String = " + nv));
}
I would greatly appreciate any help
You need to define the com.gluonhq.charm.down.android.scan.SCAN intent in your AndroidManifest.xml file. Add the following activity definition below your main activity definition:
<activity android:name="com.gluonhq.charm.down.android.scan.zxing.CaptureActivity"
android:screenOrientation="sensorLandscape"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.gluonhq.charm.down.android.scan.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
By default, the AndroidManifest.xml file is generated for you under the hood by the plugin. If you haven't setup a custom AndroidManifest.xml file yet, you can copy the one that the plugin generates. The default version is located in build/javafxports/tmp/android/AndroidManifest.xml. Just copy that one to a persistent location, i.e. src/android. Then update your build.gradle to tell the plugin that it should use the custom AndroidManifest.xml file instead of generating the default one:
jfxmobile {
android {
manifest = 'src/android/AndroidManifest.xml'
}
}
update:
You also need to add an extra dependency to the zxing core library as it seems it isn't included automatically when depending on the charm library alone:
dependencies {
androidRuntime 'com.google.zxing:core:3.2.1'
}
Furthermore, you'll have to add the CAMERA permission to your manifest as well:
<uses-permission android:name="android.permission.CAMERA"/>

AndroidTest does not use test application

Hi I faced that when I rewrite application in androidTest manifest file, it does not work. This is my AndroidManifest.xml file in androidTest folder:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="ru.app"
android:installLocation="auto">
<application
tools:replace="android:name"
android:name=".app.ApplicationAndroidTest" />
</manifest>
This is part of original AndroidManifest.xml from main folder:
<application
android:name=".app.Application"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:largeHeap="true"
android:theme="#style/Theme">
...
</application>
In fact I debugged it, and called getApplication() from breakpoint in activity under test, it returns .app.Application instead of ApplicationAndroidTest instance.
Do you have any ideas why android manifest file from androidTest is ignored?
As A workaround I used custom test runner class:
public class UiTestsRunner extends AndroidJUnitRunner {
#Override
#NonNull
public Application newApplication(#NonNull ClassLoader cl, #NonNull String className, #NonNull Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return Instrumentation.newApplication(ApplicationAndroidTest.class, context);
}
}
It seams ok for me. Hope it helps someone.
Changing application class at androidTest xml doesn't affect the app itself (tested app) but the additional android test apk that ships to the device for enabling tests. I'm not sure what is the exact meaning of application if any to android test apk.
anyhow busylee workaround is the available solution.
Important note: when defining custom instrumentation runner, it is required to run the tests with the custom runner, that can be done at Android Studio by editing run configuration of test run, under AndroidTests section with a test selected, there is 'Specific instrumentation runner (optional)' option.

Android App Users Get "App not installed" When Attempting to Update

UPDATE: To those who asked about which error codes the users are receiving: there are no error codes. It just opens a blank, post-installation page that says "The app was not installed" with a big 'X' next to it. It's possible different versions of Android could have different messages. There is no indication for what went wrong during the installation.
UPDATE 2: Some users reported that they receive error code "-504" when they try to install/update from the Play Store, and the "app not installed" message when manually trying to install the .apk. I don't know what correlation this error has with users being unable to install, but the solutions from the only 2 questions on SO on this topic did not fix anything for me. I've included the updated manifests and build files.
UPDATE 3: It appears as users report this issue in versions after IAB has been successfully installed, which further de-legitimatizes the concept that this issue is caused by introducing IAB.
UPDATE 4: It looks like the problem is with old users trying to update to a new version, and not with new users. With that in mind, there is a high likelihood that this issue is result of INSTALL_FAILED_UID_CHANGED. Looking through the version history, the significant change I made in the problematic version that users cannot update from is removing drawables that I no longer intended of using.
Asking users to go through the procedure to fix this isn't plausible. If there is a solution that I can enforce which would fix it for faulty users, wonderful... if not, the least I can do at this point is damage control and ensure this doesn't happen in the future.
NOTE: Below is the original post speculating that the problem is the result of introducing IAB into the app. Since then, it has become more and more unlikely for that to be the cause. Regardless, the post still has relevant information.
------------------------------------------------------------------------------------------
Original Title: Android App Users Get "App not installed" After Introducing IAB
I recently introduced IAB in my app that was published on Google Play. After a while, I've started to get reports from some users that they get an "installation unsuccessful" error when they try to install or update it.
What makes me think it's caused by introducing IAB is that one particular long-time user e-mailed me that when he's attempting to update to the version with IAB, the installer mentions that new permissions were introduced and requires the user's permission. Once granted, it says that the app failed to install.
I've done some Googling and it appears to be a problem from their end, one user even tried to manually install an .apk with said permissions removed without any success. I wan't to make sure that it's not something I've done wrong, but an inevitability that I have to accept with some users.
Note that the vast majority has no problem of installing the app, and I haven't received any reports of this until after IAB was introduced. It wouldn't bother me so much were it a small amount of lost users, but the problem is, those users hurt my app's rating. Users have also mentioned that they can install apps, excluding my own, perfectly well.
I don't rule out the possibility that users may have been getting these errors even before IAB was introduced, and the linkage could be a mistaken one.
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest package = "com.jjsoftware.fullscientificcalculator"
xmlns:android = "http://schemas.android.com/apk/res/android">
<uses-permission android:name = "android.permission.VIBRATE"/>
<uses-permission android:name = "com.android.vending.BILLING"/>
<application
android:allowBackup = "true"
android:fullBackupContent = "true"
android:icon = "#drawable/logo"
android:label = "#string/app_name">
<activity
android:name = ".MainActivity"
android:hardwareAccelerated = "false"
android:label = "#string/app_name"
android:screenOrientation = "portrait"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name = "android.intent.action.MAIN"/>
<category android:name = "android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name = ".SettingsActivity"
android:theme = "#style/PreferencesTheme">
<intent-filter>
<action android:name = ".SettingsActivity"/>
<category android:name = "android.intent.category.PREFERENCE"/>
</intent-filter>
</activity>
</application>
Here is the Gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.jjsoftware.fullscientificcalculator"
minSdkVersion 14
targetSdkVersion 23
versionCode 102
versionName "1.679"
}
sourceSets { main { assets.srcDirs = ['src/main/assets', 'src/main/assets/'] } }
}
dependencies {
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.google.android.gms:play-services-ads:8.4.0'
compile 'com.android.support:gridlayout-v7:23.2.1'
compile files('libs/exp4j-0.4.5.jar')
compile files('libs/EJML-core-0.28.jar')
compile files('libs/EJML-dense64-0.28.jar')
compile files('libs/Jama-1.0.3.jar')
compile files('libs/EJML-simple-0.28.jar')
}
And, if need be, the top-level build:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
There is a typo in the manifest file on line android:largeHeap="true">>. xml line ends with >>. This may be causing the error.
it could be the phones have a lower version of the Google play services than the minimum you defined in the APK.
There is nothing much you can do if that is the case, other than for the users to upgrade their google services (https://play.google.com/store/apps/details?id=com.google.android.gms&hl=en) or you reduce your version.
also you may need to add the following to your manifest. (i think this is used to compare the versions installed in the phones with the versions required by the apk)
<application ...>
<!-- This meta-data tag is required to use Google Play Services. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
I got this error while installing on my Android device a new APK for the app I am developing.
I checked the debug log on the device (using "adb -d logcat > log.txt") and found an entry saying "PackageManager: Downgrade detected: Update version code 2 is older than current 10000". Obviously something went wrong with the versioning somehow.
I uninstalled the package and then was able to install the APK with no problems.
Remember that the latest installment of Android (Marshmallow version) has changed the permissions to give more access to permissions to the user. Hence it is not enough to define the permissions in the manifest anymore.
Through code you need to make sure that the billing permission is enabled by the users when they use the app. The simplest way to go around this is to set the target SDK to v-22. This should temporarily solve your issue.
The real solution however is to handle the new permissions introduced in Marshmallow. Here is how to do it:
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch(requestCode) {
case BILLING_REQUEST:
if (canAccessBilling()) {
callBillingPerms();
}
break;
}
}
private void callBillingPerms() {
Toast.makeText(this, "We need your permission to access Billing", Toast.LENGTH_SHORT).show();
}
private boolean canAccessSMS() {
return(hasPermission(Manifest.vending.BILLING));
}
#TargetApi(Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED==this.checkSelfPermission(perm));
}
Hope this helps :)
Perhaps the error is on the user's side.
This article states the following:
Google Play - Error 504
Problem
App could not be downloaded due to an error.
First solution
The usual, please: go to Settings > Apps > All > Google Play Store and Clear cache and Clear data. Also Clear cache and Clear data for Google Services Framework.
Second solution
Try removing your GMail account
This Stack Exchange answer discussed similar ideas.
According to the list of status codes at Wikipedia, a 504 error means the following:
504 Gateway Timeout
The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
Ask your users if doing the above solves their issue.

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.

Android Gradle replace Package name for a value in manifest

I am using Gradle with Product flavors where I set a different package name for each one.
productFlavors {
appone {
packageName "com.dg.app1"
}
apptwo {
packageName "com.dg.app2"
}
appthree {
packageName "com.dg.app3"
}
appfour {
packageName "com.dg.app4"
}
}
I need to be able to replace the package name inside the manifest for each corresponding app.
My manifest has this:
<receiver android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.dg.example" />
</intent-filter>
</receiver>
So I need to replace com.dg.example for each app flavor's package name. What is the best way to do this?
Gradle Plugin v0.12 and higher:
Use ${applicationId} instead of ${packageName}.
Gradle Plugin v0.11 and higher:
As of v0.11, you no longer need to specify not to use the old manifest merger.
Gradle Plugin v0.10 and higher:
Assuming you're using version 0.10 or higher, this is now officially supported:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// Make sure this is at least 0.10.+
classpath 'com.android.tools.build:gradle:0.10.+'
}
}
As of v0.10, you'll also have to manually enable the new manifest merger, although I'd expect that requirement to go away in a version or two whenever the new merger becomes the default:
android {
useOldManifestMerger false
}
Then, just use ${packageName} anywhere in AndroidManifest.xml that you would normally hardcode the package name. For example:
<category android:name="my.package.name"/>
would become
<category android:name="${packageName}"/>
Gradle Plugin v0.9 and below:
So, referencing this post, it appears this is not yet officially supported through Gradle. A simple workaround is the following:
Replace the package name with a custom tag (e.g. <category android:name="my.package.name"/> becomes <category android:name="_PACKAGENAME_"/>
Add the following to your build.gradle, under the android scope:
applicationVariants.all { variant ->
// After processing the manifest, replace all instances of your tag
// with the variant's actual package name.
variant.processManifest << {
def manifestOutFile = variant.processManifest.manifestOutputFile
def newFileContents = manifestOutFile.getText('UTF-8').replace("_PACKAGENAME_", variant.packageName)
manifestOutFile.write(newFileContents, 'UTF-8')
}
}
To do something like this, I use buildTypes in my gradle file but I am pretty sure this will work with flavours as well. For me I am trying to set the label field in the activities.
I have a strings xml file for each of my buildTypes.
Then I have a sourceSet for each buildType which includes the correct strings file.
Then in the manifest I do not use a hard coded string but rather "#string/my_var" which will pull the correct string depending on how the sourceSets are defined.
This google+ post and related gist may help.
Something else to do is to put a AndroidManifest.xml file into the src/flavour which only contains the bits which are relevant to each flavour. Then take those bits out of the main manifest file. At build time the Manifest files will be merged into one file. You can see the result all of the merged manifests in build/manifests.
I had the same problem and implemented a placeholder replace method in Gradle. It does exactly what you'd expect but also takes care about packageNameSuffix attributes so you can have debug and release as well as any other custom builds on the same device.
applicationVariants.all { variant ->
def flavor = variant.productFlavors.get(0)
def buildType = variant.buildType
variant.processManifest.doLast {
println '################# Adding Package Names to Manifest #######################'
replaceInManifest(variant,
'PACKAGE_NAME',
[flavor.packageName, buildType.packageNameSuffix].findAll().join()) // ignores null
}
}
def replaceInManifest(variant, fromString, toString) {
def flavor = variant.productFlavors.get(0)
def buildtype = variant.buildType
def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml"
def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString)
new File(manifestFile).write(updatedContent, 'UTF-8')
}
I have it up on a gist too if you want to see if it evolves later.
I found to be a more elegant approach than the multiple resources and XML parsing approaches.
Option Gradle:
Use grade attributes API. Some thing like this
manifest.attributes(["attr1":"value1", "attr2":"value2"])
Option 1
How about converting your project to Android - library project, and making extra project for each company. Than you can edit the Manifest file as you wish.
Option 2
Write a batch file.

Categories

Resources