Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] default proguard rules for BroadcastRec…
Browse files Browse the repository at this point in the history
…eiver (dotnet#4178)

Fixes: dotnet#4110

A crash was reported when using either Proguard or R8:

	java.lang.RuntimeException: Unable to get provider mono.MonoRuntimeProvider_1: java.lang.ClassNotFoundException: Didn't find class "mono.MonoRuntimeProvider_1" on path: DexPathList[[zip file "/data/app/myApp-61Sw26LCrQQYfOvCs2GsDw==/base.apk"],nativeLibraryDirectories=[/data/app/myapp-61Sw26LCrQQYfOvCs2GsDw==/lib/arm64, /data/app/myapp-61Sw26LCrQQYfOvCs2GsDw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/product/lib64]]
	    at android.app.ActivityThread.installProvider(ActivityThread.java:7152)
	    at android.app.ActivityThread.installContentProviders(ActivityThread.java:6630)
	    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6525)
	    at android.app.ActivityThread.access$1400(ActivityThread.java:220)
	    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1883)
	    at android.os.Handler.dispatchMessage(Handler.java:107)
	    at android.os.Looper.loop(Looper.java:224)
	    at android.app.ActivityThread.main(ActivityThread.java:7520)
	    at java.lang.reflect.Method.invoke(Native Method)
	    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
	    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
	    Caused by: java.lang.ClassNotFoundException: Didn't find class "mono.MonoRuntimeProvider_1" on path: DexPathList[[zip file "/data/app/myapp-61Sw26LCrQQYfOvCs2GsDw==/base.apk"],nativeLibraryDirectories=[/data/app/myapp-61Sw26LCrQQYfOvCs2GsDw==/lib/arm64, /data/app/myapp-61Sw26LCrQQYfOvCs2GsDw==/base.apk!/lib/arm64-v8a, /system/lib64, /system/product/lib64]]
	    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:230)
	    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
	    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
	    at android.app.AppComponentFactory.instantiateProvider(AppComponentFactory.java:147)
	    at android.app.ActivityThread.installProvider(ActivityThread.java:7136)

This could be reproduced in a new project, just by enabling a Code
Shrinker and adding a `BroadcastReceiver`:

	[BroadcastReceiver(Process = ":remote", Name = "foo.MyReceiver")]
	public class MyReceiver : BroadcastReceiver
	{
	    public override void OnReceive(Context context, Intent intent) { }
	}

This generated a file in:

	obj\Release\100\android\src\mono\MonoRuntimeProvider_1.java

We have no default proguard rule in `proguard_xamarin.cfg` that would
cover inclusion of this Java class for ProGuard or R8.

We can simply add a trailing `*` to the Java class name of an existing
rule:

	-keep class mono.MonoRuntimeProvider* { *; <init>(...); }

I also added a test for this scenario that will verify ProGuard & R8.
  • Loading branch information
jonathanpeppers authored and jonpryor committed Jan 27, 2020
1 parent 1524e6e commit 55fa709
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

-keep class android.support.multidex.MultiDexApplication { <init>(); }
-keep class com.xamarin.java_interop.** { *; <init>(); }
-keep class mono.MonoRuntimeProvider { *; <init>(...); }
-keep class mono.MonoRuntimeProvider* { *; <init>(...); }
-keep class mono.MonoPackageManager { *; <init>(...); }
-keep class mono.MonoPackageManager_Resources { *; <init>(...); }
-keep class mono.android.** { *; <init>(...); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3607,6 +3607,19 @@ public void Desugar ([Values (true, false)] bool isRelease, [Values ("dx", "d8")
DexTool = dexTool,
LinkTool = linkTool,
};

//Add a BroadcastReceiver
proj.Sources.Add (new BuildItem.Source ("MyReceiver.cs") {
TextContent = () => @"
using Android.Content;
[BroadcastReceiver(Process = "":remote"", Name = ""foo.MyReceiver"")]
public class MyReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent) { }
}",
});

//Okhttp and Okio
//https://github.com/square/okhttp
//https://github.com/square/okio
Expand Down Expand Up @@ -3691,6 +3704,8 @@ public void foo()
var dexFile = builder.Output.GetIntermediaryPath (Path.Combine ("android", "bin", "classes.dex"));
FileAssert.Exists (dexFile);
Assert.IsTrue (DexUtils.ContainsClass (className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!");
className = "Lmono/MonoRuntimeProvider_1;";
Assert.IsTrue (DexUtils.ContainsClass (className, dexFile, AndroidSdkPath), $"`{dexFile}` should include `{className}`!");
}
}

Expand Down

0 comments on commit 55fa709

Please sign in to comment.