[Android General] admicos:
notice: I have only tried this with two APKs, with similar versions. Older or newer versions might differ. Here be dragons.

If you're someone like me, who don't install Google apps on your phone for one reason or another, but still want to use Google Camera for the quality improvements it brings, this topic might help you out!

If you didn't know, not having Gapps installed will usually make Google Camera crash right away, even if your phone's compatible with the mod you are using. My workaround for this was setting up microG and disabling it's Google server connections, but I wanted to learn modding APKs, so I thought this would be a good way to start on it. Fortunately, this was very easy to do, as not many features depend on Gapps.

Requirements:

Intermediate knowledge on Android tinkering

A GCam APK for your phone, preferably one that can disable Google Photos and Lens integrations (which will probably stop working with this patch)

apktool

adb

1. Open the camera and get the crash stacktrace through adb logcat. You will need this to find out which class to edit.

In the following stacktrace snippet, the bolded part is what you will be looking for. For the rest of this guide, the name of the class is assumed to be 'kas'.

java.lang.RuntimeException: Unable to create application com.google.android.apps.camera.legacy.app.app.CameraApp: java.lang.SecurityException: Failed to find provider com.google.android.gsf.gservices for user 0; expected to find a valid ContentProvider for this authority
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5743)
at android.app.ActivityThread.-wrap1(Unknown Source:0)
<snip>
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.SecurityException: Failed to find provider com.google.android.gsf.gservices for user 0; expected to find a valid ContentProvider for this authority
<snip>
at android.content.ContentResolver.registerContentObserver(ContentResolver.java:1924)
at android.content.ContentResolver.registerContentObserver(ContentResolver.java:1913)
[B] at kas.a(Unknown Source:34)
at kas.b(Unknown Source:3)
at kas.a(Unknown Source:0)[/B]
at com.google.android.apps.camera.legacy.app.app.CameraApp.onCreate(Unknown Source:33)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1119)
<snip>

2. Decompile the APK, and find the class

Not much to explain here. apktool and the find command (for *nix at least) should work pretty well. You will probably find it under ./smali.

3. Find some interesting fields

In the smali file, near the top, you will see two private static final fields with the type of android.net.Uri. In my case, they are named b and c (will refer to them as kas.b or kas.c from now on)

.field private static final b:Landroid/net/Uri;
.field private static final c:Landroid/net/Uri;

Inside the constructor you should find two strings with com.google.android.gsf.gservices. We need to trace the constructor to find out which one maps to which field:

const-string v0, "content://com.google.android.gsf.gservices"
invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
move-result-object v0
sput-object v0, Lkas;->c:Landroid/net/Uri; # put v0 into [B]kas.c[/B]. this might be referred to as [B]field 1[/B] later on

const-string v0, "content://com.google.android.gsf.gservices/prefix"
invoke-static {v0}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
move-result-object v0
sput-object v0, Lkas;->b:Landroid/net/Uri; # put v0 into [B]kas.b[/B]. this might be referred to as [B]field 2[/B] later on (URI ends with /prefix)

This step is needed because the order of these fields change between versions and different obfuscations.

4. Delete the broken parts

Now, do a search for ContentResolver;->registerContentObserver in the file. There should be a single result.

Go upwards and find the sget-object call for field 1 (kas.c).

Delete everything in between, and including, sget-object and invoke-virtual

Then, do another search for Lkas;->b (kas.b / field 2), and find the only sget-object line containing it.

Then, delete the invoke-virtual/range and the following move-result-object lines.

Scroll a little lower, and replace the if-eqz v1 line after the new TreeMap with a goto.

5. Pack it up

Build the APK, sign/align and push into your phone. It should be good to go!