using R8 to hide private and internal methods from android library - android

i have written android library. but when i integrate aar into client app. i can actually see private/internal/public methods of "public" classes.
what i expect is: it should show only "public" methods of "public" classes.
i am using R8, for release build i have following settings in library gradle file.
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
}
proguard-rules.pro file contents:
-keep class com.comp.sdk.UserManager {
public *;
}
here UserManager is 'object' in kotlin.
after building aar file. distributing to client app. client app can still see
private/public/internal methods for UserManager object.
my question is how can i write r8 rules for showing only public methods/variables of User object in kotlin?

Related

Undo from enable minify after release the app

At some point of devlopment I changed minifyEnabled to true without any rules in proguard then release the app to google play with v.1.4.0.
many of bugs occured to uses when updated the app, I knew the problem because the obfuscated of classes.
and some of users removed the app and reinstall to work well partially.
WebView, Camera, Gson, File Picker all this features have problems on version 1.4.0
It was my first experience with minifyEnabled, now I'm knowing that there are alot of rules should I write in the proguard to keep classes.
My question about make undo of minifyEnabled and set it to false, when I debug it, also a new problem occurs and one of them from the code below with NullPointerException.
abstract class LiveCoroutinesViewModel : ViewModel() {
inline fun <T> launchOnViewModelScope(crossinline block: suspend () -> LiveData<T>): LiveData<T> {
return liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
emitSource(block())
}
}
}
note: I don't need to keep minifyEnabled = true, becuase I have alittle bit experinces and I think there are alot of keeping rules should I understand before I write them and I don't have the time now for that.
So, what is the optimal soultion (strategy) to do minifyEnabled = false for users which already working on minifyEnabled = true
The answer is not possible in my way. Because you don't have an option to handle your released app code.
My Suggestion:
Do you think that you have to write rules for Proguard? But not, Android proguard is R8 Guard not proguard. Proguard is another company guard(DexGuard). You can use the R8 guard without adding any rules because these rules are already included in all libraries(read library github and check R8 is included or not). If you enabled R8 guard then just add this line #Keep in your Model class to prevent R8 Guard to shrink that file. Add #Keep which file you don't want to minify.
Like this
#Keep // use to prevent R8 to minify this class.
public class ModelClass {
String id;
String text;
String image;
public String getImage() {
return image;
}
In new version of android, You can test your app by enabling R8 guard in debug mode by adding these below lines in your build.gradle(:app); // in module level
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug { // add this line after release and make ninify true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
It may take some time to build but it is a very good method to test if the app is caching or not (in app build time).
PS
minifyEnabled true helps to reduce app size. Very helpful if you enabled it.
It helps you in the future.

R8 changes "protected" methods of abstract class to "public" without -allowaccessmodification flag

I have an issue with R8. In MyLib I have public abstract MyLibsClass in which I have protected methods. MyChildClass extends from MyLibsClass in MyApp and after R8's magic all protected methods (including protected abstract) in MyLibsClass are changed into public ones, and of course in MyChildClass I'm getting "attempting to assign weaker access privileges ('protected'); was 'public') issue as trying to override protected abstract methods.
Additional info
gradle-6.0.1
MyLib's build.gradle
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
}
proguard-rules.pro
-keep class com.example.mylib.*{
public protected *; }
-keep class com.example.mylib.*$*{
public protected *; }
Anyone had this kind of issue or know a way to fix this?
So based on discussion here ,
DON'T USE DEFAULT PROGUARD SETTINGS FOR LIBRARIES
as allowAccessModification is enabled in default proguard settings, which is located in Android SDK (\Android\Sdk\tools\proguard\proguard-android-optimize.txt) and my mistake was using this for my libraries.
Citation from proguard manual
you probably shouldn't use this option when processing code that is to
be used as a library, since classes and class members that weren't
designed to be public in the API may become public.
So if anyone has the same issue I will suggest to create your own base config file for proguard and copy past whole default configs without "allowAccessModification" into it.
Also if someone interested more, you can track this issue. Hopefully will get separate config file for libraries in near feature.
I faced the same problem, and thanks to #Hayk Nahapetyan's answer, I could resolve it.
Here is my solution with a little more detail.
In the library module's build.gradle, remove the default file from the buildTypes's release closure:
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
R8 no longer uses the default file that is provided in the Android SDK. It generates one at build time, and puts it in the module's build directory at build/intermediates/default_proguard_files/global.
Copy the contents of proguard-android-optimize.txt-a.b.c (where a.b.c is the library version, if set) from that location to the top of the module's proguard-rules.pro. Then remove -allowaccessmodification; two times, if it originally appeared in both files.
This was also reported on the R8 bug tracker, and resolved there. See http://issuetracker.google.com/147447502.

App server data fetch in debug mode but doesn't work in release mode

I am fetching data from server it is working fine in debug apk but I am trying on generate signed apk, data is not fetching data from server.
Is there any way to get solution?
Proguard may be causing that issue. Please check if it is enabled in your app's gradle file.
These lines enables proguard for release build:
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
If yes then you will need to keep some fields.
See this: https://developer.android.com/studio/build/shrink-code
You need to add #Keep annotation for all your network models (if you or your libs uses reflection). Because proguard obfuscate all classes in signed apk and Gson can`t parse JSON to you model.
EDIT:
for example you have class for parse from json (NetworkResponse.java class):
#Keep
public class NetworkResponse {
// fields of class...
}

Android ProGuard how to hide/obfuscate source code of exported library

I'm developing Android library and I want to hide/obfuscate the source code implementation of the library.
The way the user project app will use the library is:
startActivity( new Intent(context, LibraryActivityName.class) );
So I need to keep just the name of entry point Activity inside the library project, That's all.
When I used the default ProGuard settings:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
as well as the suggested example for library - Nothing happened, and by clicking on the Activity name inside the user app (when he imports it) - One can see the source code.
Thanks,
As you do not have a typical library, you should not include the typical library example.
First of all, you need to enable Proguard execution, change this line:
minifyEnabled true
Second, you do not want to keep all public classes, but only the activity:
-keep class LibraryActivityName { public protected <methods>; }
The remaining classes can be fully obfuscated if I understand your question correctly, so there should be no need for further configuration, unless you use reflection somewhere.
It would also be good if you repackage the obfuscated classes into an internal package or something using
-repackageclasses my.library.package.internal
which might also required
-allowaccessmodification
btw. ProGuard will not obfuscate the code itself, only the class / method names.

Proguard fails with RetroLambda and custom build type

I'm trying make use of Lambda expressions in my Instrumentation tests in my Android app, but they fail with the following error each time I build:
:myapp:proguardItestAndroidTest
Warning:com.myapp.OfflineTests: can't find referenced class java.lang.invoke.MethodHandles$Lookup
Warning:com.myapp.OfflineTests: can't find referenced class java.lang.invoke.MethodHandles
Now these errors are well known, and usually fixable with the following line in proguard.txt:
-dontwarn java.lang.invoke.*
..and it does in the release and debug build, but not the custom build type "itest" I've made. Anyone got any explanation for that? I am indeed specifying the same proguard rule files for the itest build as for the release:
itest { // Needed because I-tests needs special permissions (turn on/off wifi)
minifyEnabled true
proguardFiles 'proguard-rules.txt', '../lib/proguard-common.txt'
signingConfig signingConfigs.release
debuggable true
ext.enableCrashlytics = false
}
edit: I know that the file is correctly loaded becuase the task proguardItest runs successfully, but fails if I empty the file. It is the task proguardItestAndroidTest that fails

Categories

Resources