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

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.

Related

What is the function or usefulness of the code below in Firebase? [duplicate]

I have an app that utilises Fabric's Crashlytics via Firebase.
The following is the first thing executed in my Applications onCreate
CrashlyticsCore crashlyticsCore = new CrashlyticsCore.Builder()
.disabled(BuildConfig.DEBUG)
.build();
Fabric.with(this, new Crashlytics.Builder().core(crashlyticsCore).build());
Nonetheless, the crashes are submitted in DEBUG == true mode.
I use the following versions
in my build.gradle
classpath "io.fabric.tools:gradle:1.25.1"
in my app/build.gradle
implementation "com.crashlytics.sdk.android:crashlytics:2.9.1"
Unfortunately the crashes still get reported. Any ideas, what I am doing wrong?
Correct answers have been posted by Bob Snyder and niqueco already however it seems kinda tedious to change the meta-data value every time you are building an actual release APK thus here's a solution that uses so called manifestPlaceholder and changes the value automatically to trueor false depending on the buildType.
Add the following to your apps build.gradle
android {
// ...
buildTypes {
debug {
manifestPlaceholders = [enableCrashReporting:"false"]
}
release {
manifestPlaceholders = [enableCrashReporting:"true"]
}
}
}
And this to your AndroidManifest.xml
<manifest ... >
<application ...>
// ...
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="${enableCrashReporting}" />
</application>
</manifest>
You can verify the current value by clicking on the Merged Manifest tab once you have opened the AndroidManifest.xml. You should see something like this:
The Firebase Crashlytics documentation explains that once reporting is enabled in an app session, it cannot be disabled.
By default, Crashlytics reporting is enabled in a ContentProvider named CrashlyticsInitProvider that executes before your Application instance is created. CrashlyticsInitProvider enables or disables reporting based on the meta-data value firebase_crashlytics_collection_enabled, which by default is true.
If you want reporting disabled, it's critical that the manifest meta-data be present and set to false:
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
Look in the logcat during app initialization for the message:
CrashlyticsInitProvider: CrashlyticsInitProvider initialization successful
If the message is present, firebase_crashlytics_collection_enabled is true. If the message is not present, you have successfully set the meta-data to disable crash reporting.
If the meta-data is missing or set to true, you cannot disable reporting in your code using a call to Fabric.with(...).
In a comment to another answer, you indicate that you tried disabling reporting using the meta-data and were not successful. Check for a typo and ensure the declaration is correctly placed in the <application> element. In my tests, I am able to disabling reporting using the meta-data and then enable at run time.
I've finally found the issue. Crashlytics is initialized from a content provider, so by the time you try to disable from Application's onCreate() it's too late. Going through the decompiled code I've seen that you can disable that initialization by adding metadata to the <application> element in the manifest.
So, what I do is this... I've added this to app/src/debug/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><!--suppress ALL -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="<your app package>">
<application>
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />
</application>
</manifest>
I've also disabled Crashlytics in the app module gradle build file by adding:
debug {
ext.enableCrashlytics = false
}
To my surprise I didn't need to do the Fabric.with(...) thing. The above was enough.
It's working fine: no reports.
I think it is possible to do it from code as well if you switched to firebase crashlytics and removed fabric crashlytics :
link to firebase doc
So in the onCreate of your application class :
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG);
Got this information from android documentation
Customize your Firebase Crash Reports
Enable opt-in reporting:
By default, Firebase Crashlytics automatically collects crash reports for all your app's users. To give users more control over the data they send, you can enable opt-in reporting instead.
To do that, you have to disable automatic collection and initialize Crashlytics only for opt-in users.
Turn off automatic collection with a meta-data tag in your AndroidManifest.xml file:
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
Enable collection for selected users by initializing Crashlytics from one of your app's activities:
Fabric.with(this, new Crashlytics());
You need to disable Crashlytics of app’s build.gradle. Disable Crashlytics for Debug Builds
android {
buildTypes {
debug {
// Disable fabric build ID generation for debug builds
ext.enableCrashlytics = false
...
If you would like to completely disable Firebase Crash reporting AND also not have to add the
com.crashlytics.sdk.android:crashlytics:2.9.1
dependency, then follow #reVerse's answer but also add this to your AndroidManifest.xml:
<application ...>
// ...
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="${enableCrashReporting}" />
<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="true"/>
</application>

Can I enable multidex in Android debug build only?

Dears,
I read in many blog posts that multidex apps startup is slower than normal apps.
My app uses a lot of libraries that exceed 64k methods so I use multidex. But when I use proguard in release build, the final apk becomes less than 64k methods
So My question is: Can I enable multidex in Android debug build only so I don't have runtime error? and disable multi dex in release build as I don't need it?
If yes, how ?
If No, Is Android smart enough to speedup startup as it should recognize that app didn't exceed 64k even if it is multi dex app ?
Yes, you can. When you declare your buildTypes include multidex only for debug:
buildTypes {
release {
multiDexEnabled false
    }
debug {
multiDexEnabled true
}
}
Instead of enabling multidex only for debug, you can change your min sdk version to 21 only for debug so gradle can speed up dexing with ART:
android {
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion 14
}
}
...
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
http://developer.android.com/tools/building/multidex.html
suggested methods are not needed anymore as android studio became "smart enough".
In fact, it will now give you a warning when you use minSdkVersion 21 (the old way) to speed up build time with dex:
You no longer need a dev mode to enable multi-dexing during
development, and this can break API version checks less...
In the past, our documentation recommended creating a dev product
flavor with has a minSdkVersion of 21, in order to enable multidexing
to speed up builds significantly during development. That workaround
is no longer necessary, and it has some serious downsides, such as
breaking API access checking (since the true minSdkVersion is no
longer known.) In recent versions of the IDE and the Gradle plugin,
the IDE automatically passes the API level of the connected device
used for deployment, and if that device is at least API 21, then
multidexing is automatically turned on, meaning that you get the same
speed benefits as the dev product flavor but without the downsides.
Yes, it even works with the multidex support library for Android versions prior to Lollipop with a little trick.
First specify multiDexEnabled for the debug build in build.gradle:
buildTypes {
...
debug {
...
multiDexEnabled true
}
}
Then create an AndroidManifest.xml file under src/debug.
src/debug/AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name="android.support.multidex.MultiDexApplication"
tools:replace="android:name"/>
</manifest>
That should do the trick. If your app uses a custom application class then you have to create a subclass of your application class and specify the name of that subclass in the manifest.
The application subclass should look like this:
public class MyDebugApplication extends MyApplication {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}

Android Gradle Build Variant Deploy

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..."

how to manage debug and release version on android device?

I'm new to Android dev and I'm almost ready to release a first version of my app :)
While testing the signed release apk on my phone, it refuse to install because the debug version is installed with the debug signature.
So I have to uninstall the debug version but it delete all my database (and it will do it to my friends who are testing it).
Is there a way to manage a debug and a release version of the same app without losing data?
Many Android projects are starting to use the gradle build system (we transitioned to it when we started using Android Studio). Fortunately, gradle makes it really simple to install both a dev and release version simultaneously, each with their own independent data. The Android docs cover this, just add a applicationIdSuffix to your debug build type like so:
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
}
I'm not aware of any easy way to do get around the uninstall/reinstall process, so your options include...
Buy a second device for testing (some Android devices are very cheap now, especially on eBay)
Use the emulator for testing
I see the same issue, but it's to be expected, so I use the phone for debug dev, and the tablet for production testing. When I'm close to a release, I test the production version on both devices and the emulator.
With your testers, I'd advise that you always give them release versions, but you could include extensive logging to help with problems. Debug versions are then only used by you, and release versions by them. If you provide testers with a release version, they use, and accumulate data, when they come to upgrade to the next version, the data can be retained (or updated, if you change the schema) to migrate their data.
I don't see a need for your testers to be using debug & release versions.
Thanks #Evan your solution works perfect:
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
}
To append " (DEBUG)" to your app title when running in debug mode, place this code in your Activity's onCreate:
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
//The .debug specified in gradle
if (pInfo.packageName.equals("YOUR_PACKAGE_NAME_HERE.debug")) {
setTitle(getTitle() + " (DEBUG)");
}
Why uninstall the app? Normally, installing the new version of the same app (identified by the package ID) retains all the app data.
EDIT: to retain app data by hand, copy it from /data/data/my.package.name/... to a safe place, then restore when necessary.
Configure the application id suffix
With the following configuration on your app build.gradle, the release variant will use com.example.myapp applicationId, and the debug variant com.example.myapp.debug
android {
defaultConfig {
applicationId "com.example.myapp"
...
}
...
}
buildTypes {
debug {
applicationIdSuffix ".debug"
...
}
release {
...
}
...
}
Configure multiple Firebase Accounts
If you use Firebase, you will need two Firebase accounts, one for production, and the other for development.
You have to configure Google Services JSONs for each account on its own variant source set:
The production google-services.json on the release source set: app/src/release/google-services.json
The development google-services.json on the release source set: app/src/debug/google-services.json
Providers authorities
If you have defined a provider in your AndroidManifest.xml, now you could have a conflict if both release and debug variants use the same provider authorities and you have both apps installed on the same device. To avoid this issue, a good practice is to use the applicationId as the authority suffix.
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
</provider>
Custom icon for each variant
If you are going to install multiple variants on the same device, a good idea is to use different app icons, so you can identify them on the launcher.
You just need to design a debug app icon and locate it on src/debug/res/mipmap-xxhdpi-*
Configure FCM
Now that you use different Firebase Accounts, if you have an FCM (push) server, you will need to configure it with the correct credentials.
When a device with the debug app is registered, the FCM server needs to associate the registration token with the debug build type. So, when a push is sent, the token of the Firebase debug credentials is used.
So, you will need to send the build type to the FCM server, every time the app registers the FCM token.
The following article gives more info about this topic: Install your debug & release variants on the same device
For me, I also needed to add:
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
Otherwise, both would receive the same C2D_MESSAGE permission which resulted in:
Failure [INSTALL_FAILED_DUPLICATE_PERMISSION perm=<your applicationId>.permission.C2D_MESSAGE pkg=<your applicationId>]

Android: how to mark my app as debuggable?

I want to debug my app from my phone. How do I sign my app so I can do this? I don't know much about the manifest.
By putting android:debuggable="true" in your manifest file, application will go in debug mode, that means android will manage all logs file regarding your application. But make sure put it again false(or remove this tag) if application will going to live or for release mode.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application android:icon="#drawable/icon"
android:debuggable="true"
With the new Gradle build system, the recommended way is to assign this in the build types.
In your app module's build.gradle:
android {
//...
buildTypes {
debug {
debuggable true
}
customDebuggableBuildType {
debuggable true
}
release {
debuggable false
}
}
//...
}

Categories

Resources