is there a simple way to have installed two version of the app on the same android Phone?
Im updating a old web app to a native android app. For testing purpose it would be great if we could have both installed at the same time on the same device.
It would be great to rename the update just temporary.
If I rename the package name in the AndroidManifest, then also R will be renamed and I have to reorganize the imports etc.
Is it possible to do a simple rename only somewhere in the AndroidManifest without changing a single line of code (even not with eclipse / android studio refactoring mechanism).
I have tried to mark my native app as library project and to include it in a new Android Project with another package name. But I will get trouble with this approach, for instance with actionbar sherlock:
Unable to execute dex: Multiple dex files define Lcom/actionbarsherlock/R$attr;
Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lcom/actionbarsherlock/R$attr;
If you are using new gradle build system you could create new build type and then just add packageNameSuffixto it. This will add suffix to your package name but everything else stays the same.
buildTypes {
debug {
packageNameSuffix ".debug"
}
}
There is an easy way if you want to do it temporarily. You need to modify the AndroidManifest.xml file.
Find the line that looks like this:
manifest package="com.example.myapp"
and change it to something like:
"com.example.myapp.debug"
AFAIK there is no way other than changing the application package name, but it's fairly easy.
In Eclipse, right-click your project and select Android Tools > Rename Application Package.
Related
I have a project tree (a Solution in terms of Visual Studio) with some Executable and AAR library modules.
I need to get something like this in their build.gradle files..
buildTypes {
release {
//if not exist :- create extra folder in standard or customised output folder
//with the name 'Release'
//say builder to put the release build version into this folder with
//names ModuleName.aar or .apk
}
debug {
//if not exist :- create extra folder in standard or customised output folder
//with name 'Debug'
//say builder to put the debug build version into this folder with
//names ModuleName.aar or .apk
}
}
I've spent 2 days looking for a documentation how to do that.. I found just fragmentary parts of some specific settings, which ain't interesting now.
Actually, I want to get the same behaiviour of the compiler and builder as it's in Visual Studio
ProjectBuildDir\Debug\ModuleName.aar
ProjectBuildDir\Release\ModuleName.aar
Please, if you know, this would be very good to share that knowledge..
Otherwise.. I think I'll spend whole week without success.. or refer to full documentation of how to program gradle build code.
UPD: I've seen such kinds of solution, but it makes my project structure unreadable by AS. It denies to sync project with its gradle.. it hides Tool window "Build variants".. it hangs on AS itself.. :)
Maybe it happens because it's applied to Module (AAR library)?
I don't know.. I just also unable to compile and build the release version :)
I can see debug but whem I change variamt in that Tool Window in front of the AAR-Module name - then run Rebuild (Clean and Sync..) - there is no any realease in the output folder.
And I can't find the description of this meta language..
I use the AAR as Android UserControl library - extended View.. because it's handy to develop it as separate module.. simply faster..
I am the Android-kid, but MicroSoft-man :) need to see the logic of the project meta data language..
I have been trying to import a file to android studio that I decompiled using apktool. But when I try to import the file to Android studio it does not show anything on the "Project" browser. While in the import process, in the first step, I chose "Create project from existing sources". Is there anyway to fix this problem? Also, is there anyway to use in android studio a file from notepad++?
Thanks.
As Daniel Souza replied, apktool is just a tools to help you to extract the class and manifest. If you look into the detail and the flow of the Android build process (https://source.android.com/source/jack.html),
you will know every class will be obfuscated, packed and put it into the .dex file(include your own classes, android support library and other 3-party libraries).
Normally, the .apk file only included the following types of file.
.dex files (it might be not only one if the problem of 65K methods exists)
manifest( Android permission and features meta-data)
asset (Drawable, asset folders, layout and R)
Therefore, when you used apktools and some other tools(j-soup) to do some reverse-engineering. You can only have the source files only. And as Daniel method, you can import the project to the android studio but many errors might be existed into your project.
R.java cannot be generated (since all the custom id value will be converted to be a unqiue integer in the apk., this cannot be reversed as human-readable meaning even you use the apktool)
Obfuscated class and variable name. As I mentioned the process of how the apk built, the class and variable name will be obfuscated after building. Reverse engineering will be difficult to findout the logic inside the application since almost all the name are renamed as (a,b,c,d,e...)
Proguard problem, some application might use advanced technologies to compile the source code using more complex logic flow ( like Dexguard did). After you finish reverse engineering, it will be more difficult to findout the inside logic in the application.
If it is a "Simple" application, you might be able to find out what happen in the obfuscated code.
If it is a "Complex" application including a lot of libraries, it will be disaster if you are trying to dig out the logic inside it.
apktool is a reverse engineering tool that generates the source, but not the gradle build scripts, which is why it does not show up as a project you can open. You have to "import from existing sources" because apktool only generates the source files and Android Studio will attempt to fill in the gradle build files.
Once you import the project, you can add any files you like to your project's directory. This includes ones that you generate from other programs including Notepad++. You can do this in Android Studio with from Project View (Alt+1) with Copy/Paste or Drag/Drop .
I've created a project that have 3 dependencies for 3 different android projects marked as libraries. I managed to run the application from eclipse and everything works fine.
The problem: I've exported the project as a signed apk. The apk was created and I was able to run it on my device but when it tries to access an activity that resides in one of the android library my app crashes with ActivityNoFoundException. It seems that the android library projects were not added in the final apk, but why?
All the manifest files are merged into the main manifest file.
What can be the problem? Thank you!
Does your project use proguard obfuscation? it's possible the activity names are being obfuscated and therefore would not match up with what's in your manifest. Usually obfuscation isn't run when you run the app from an IDE so could also explain why it works there. You could also try unzipping the apk and looking inside to see what is actually making it in
Migrating from eclipse to Android Studio. Here is AS's build dir structure
Question 1. Where does gradle put all the compiled .class files? Is it the projectRoot/build/intermediates/classes directory?
The purpose of this question is a Java class is generated at build time (eg: CustomBuildInfo.java) and needs to added to the complied dir so that other src files can use it and packaged correctly within APK.
Note:Previously in Eclipse this generated file use to reside inside projectRoot/gen/<package> directory.
Question 2. Whats the correct location for custom generated Java files? Is it build/generated/r/<buildType>/<package> ? (this is where R.java resides)
Note But this custom generated Java file CustomBuildInfo.java belongs to common source i.e., used by all build types and all flavors
Any help will be appreciated.
To answer my own question when using GRADLE build system
Java Byte Code location (post-compilation) <projectroot>/build/intermediates/classes/<build-type>/....
assets
<projectroot>/build/intermediates/assets/<build-type>/....
res
<projectroot>/build/intermediates/res/merged/<build-type>/....
JNI libs (configurable)
<projectroot>/build/intermediates/jniLibs/<build-type>/....
Manifests
<projectroot>/build/intermediates/manifests/full/<build-type>/....
Java class generated from AIDL
<projectroot>/build/generated/source/aidl/<build-type>/....
R.java
<projectroot>/build/generated/source/r/<build-type>/....
BuildConfig.java
<projectroot>/build/generated/source/buildConfig/<build-type>/....
Test reports HTML
<projectroot>/build/reports/tests/<build-type>/index.html
APK output files
<projectroot>/build/outputs/apk/...
Lint Results
<projectroot>/build/outputs/...
Manifest Merger Report (if using multi-module build)
<projectroot>/build/outputs/logs/...
Test Results
<projectroot>/build/test-results/...
Intermediate classes can sometimes be stored at "../build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" for the debug build classes and at "../build/intermediates/javac/relese/compileReleaseJavaWithJavac/classes" for the release build classes. And sometimes they can be stored at "../build/debug" for debug classes and at "../build/release" for release build classes.
I'm not sure what causes them to be in one place or the other. If you look at the ".impl" file (which contains xml) for the module your interested in you will find an entry like this:
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
or an enty like this:
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
That's what determines where the intermediate classes will be stored for the module. Why it's sometimes in the 'build/intermediate/classes' directory and sometimes in the 'build/intermediate/java' directory has me baffled. I've look for various reasons such as 1.) is it affected by the manisfest, 2.) manifest merging 3.) jdk version 4.) module type (application, android library, java library), 5.) use of instance run. In all my attempts to see what causes it to choice one or the other, I've not been able to determine how that decision is made. If someone knows what factor determines the directory scheme choice , please add the reason.
If you're like me and have a reason want to get access to the intermediate java classes produced, the easiest work around is to see which directory exist. You'll have one or the other, but not both!
Background
I'm working on an app that has become very popular, so much that a part of it is supposed to become an SDK (which would be available for developers), and the app will split to 2 apps (both use the SDK).
According to what I know, there are multiple ways to create an SDK module (previously called "project" on Eclipse) :
Completely open sourced (Android library) - all sources and resources are open sourced and can be modified. An example might be Facebook's SDK and a lot of Github repos.
a single Jar file, which can be closed sourced.
The problem
Sadly, I can't make the SDK open sourced, and it should relatively be protected vs prying eyes (obfuscated etc...).
The issue here is, the SDK needs to use some resources of its own (drawables, strings,...), and so far (because I didn't have a lot of experience with creating SDKs) I've found 2 ways to handle resources for SDKs :
use reflection and/or "context.getResources().getIdentifier" . This is quite messy, as I lose the whole "R" usage of the code. Also, it has issues with "styleable" , as I've written here. It also makes it hard to find unused resources.
even worse ways: put resources in assets folder, put files in a wacky way inside the jar file, ...
Note that a part of the SDK includes custom views (for example, classes that extend from TextView), so even if I do split the SDk into 2 modules- resources and java files, both might have issues of dependencies (each uses the other one).
The question
Is it possible to somehow solve this issue?
Is it possible for the code part of the SDK to remain closed sourced, reach the "R" file as usual, and make it easy for both me and whoever use the SDK ?
How would I then generate the jar file as being obfuscated via Android Studio? and is it possible to prepare it to to be used via gradle afterwards?
Can I maybe make the Android-library of the SDK into an obfuscated jar file and not worry about the "R" file ? I ask this because this way I could enjoy both worlds: for our apps, it would remain open sourced, and for third party apps it would be closed sourced.
EDIT: seeing that this is supposed to be easy, I've tried it myself. I've created a totally new POC project which has an Android library module called "sdkmodule", and added this class to it:
public class SdkClass
{
public String doIt(Context context)
{
return context.getResources().getString(R.string.app_name);
}
}
Then, I've made the app's module to use this one, and I wrote this code in it:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SdkClass sdkClass=new SdkClass();
Log.d("AppLog","string from SDK:"+sdkClass.doIt(this));
Log.d("AppLog","string with same ID name from app:"+getResources().getString(R.string.app_name));
}
What I expected is that the first log would print the string that's in the SDK module, and the second to show the string of the current project, but instead I got an exception:
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/example/user/sdkmodule/R$string;
On another try, I've got the same string that's used on the app itself (the one that uses the SDK module). And, on another run, the SDK produced the needed string as I've wanted.
How could it be? What should I do ?
In addition, I've tried to make a second activity in the SDK itself, and I've created a resource there that has the same resource name (used for a textView in its layout) as of the app itself, yet with a different value, yet when I've reached this activity, I've seen the one used by the app.
Here's the project, zipped (ignore the name of the folder, I wanted to try flavors too) :
https://drive.google.com/file/d/0B-PZZGk2vPohX25WUDNKTmotUTg/view?usp=sharing
The answer to your problem is to package and distribute your library as an AAR bundle
This format allows you to provide an obfuscated SDK jar and with its resources and the R mapping file.
This format is a standard and fully supported by maven-android-plugin (actually it's the replacement of the old APKLib format which supports only the distribution of source files).
Of course it's also supported by Gradle and Android Studio.
The Android Archive (AAR) format does what you want. It's like an Android-specific JAR file and contains compiled code, but includes its own resources and manifest. You can also include obfuscation as part of the build process. By default, the current version of Android Studio (1.2) and Gradle automatically build .AAR files for all library modules you create in your project.
You can change an app module into a library project that will publish an AAR file just by changing apply plugin: 'com.android.application' into apply plugin: 'com.android.library' in your module's Gradle file. The .AAR file will be placed in your MODULENAME/build/outputs/aar folder after each build. Some more information is available here.
Edit 1, after question updated:
The resources in your AAR get consolidated with the app module when the final APK gets compiled. The app resources will override the library's. This is probably by design, to allow people using a 3rd party library to customize its resources when creating their app, without having to rebuild the library. I think the easiest way to solve your resource conflict issue would just be to name your sdkmodule resources something more unique. Why not make the string key R.string.com_example_sdk_name or something?
No, the AAR libraries don't get obfuscated by default, but you can set up ProGuard in the Gradle build file for your AAR library to take care of this. Other tools are also available.