Android Bundle App内部实现原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010479969/article/details/81261040

core中的代码

首先我们在代码中调用了

manager = SplitInstallManagerFactory.create(this)
1.SplitInstallManagerFactory.class
public class SplitInstallManagerFactory {
    public static SplitInstallManager create(Context context) {
        return new h(new k(context), context);
    }
}

2.com.google.android.play.core.splitinstall.k.class

final class k {
    private static final b b = new b("SplitInstallService");
    private static final Intent c = new Intent("com.google.android.play.core.splitinstall.BIND_SPLIT_INSTALL_SERVICE").setPackage("com.android.vending");
    final com.google.android.play.core.a.b<a> a;
    private final Context d;
    private final String e;
    private final f f;

    public k(Context context) {
        this(context, context.getPackageName());//这个是需要传给Google play的包名
    }

    private k(Context context, String str) {
        this.f = new j(this);
        this.d = context;
        this.e = str;
        this.a = new com.google.android.play.core.a.b(context.getApplicationContext(), b, "SplitInstallService", c, l.a, this.f);
    }

可以看到直接调用到了c这个service,我们在自己代码里没有找到这个相关Service,

我们反编译Google play和Google Play Service发现这段代码在google play的应用商店中。

3.Google Play的代码:

        <service finsky:name="com.google.android.finsky.splitinstallservice.SplitInstallService" finsky:enabled="true" finsky:exported="true" finsky:visibleToInstantApps="true">
            <meta-data finsky:name="instantapps.clients.allowed" finsky:value="true" />
            <intent-filter>
                <action finsky:name="com.google.android.play.core.splitinstall.BIND_SPLIT_INSTALL_SERVICE" />
            </intent-filter>
        </service>

4.现在流程基本上打通了,下面看看我们安装的时候,代码流程。

    private fun loadAndLaunchModule(name: String) {
        updateProgressMessage("Loading module $name")
        // Skip loading if the module already is installed. Perform success action directly.
        if (manager.installedModules.contains(name)) {
            updateProgressMessage("Already installed")
            onSuccessfulLoad(name, launch = true)
            return
        }

        // Create request to install a feature module by name.
        val request = SplitInstallRequest.newBuilder()
                .addModule(name)
                .build()

        // Load and install the requested feature module.
        manager.startInstall(request)

        updateProgressMessage("Starting install for $name")
    }

5.manager.startInstall

进入com.google.android.play.core.splitinstall.h中:


    public final Task<Integer> startInstall(SplitInstallRequest splitInstallRequest) {
        if (!getInstalledModules().containsAll(splitInstallRequest.getModuleNames())) {
            return this.b.a(splitInstallRequest.getModuleNames());//这个就是前面的k.class
        }
        this.f.post(new i(this, splitInstallRequest));
        return Tasks.a(Integer.valueOf(0));
    }

6.回到com.google.android.play.core.splitinstall.k.class

    public final Task<Integer> a(Collection<String> collection) {
        b.a("startInstall(%s)", collection);
        i iVar = new i();
        this.a.a(new m(this, iVar, collection, iVar));
        return iVar.a();
    }
    //我的理解这个应该走下面,但实际走的是上面(安装/卸载)
    public final Task<Void> a(List<String> list) {
        b.a("deferredUninstall(%s)", list);
        i iVar = new i();
        this.a.a(new n(this, iVar, list, iVar));
        return iVar.a();
    }

7.进入:com.google.android.play.core.a.b中

    public final void a(a aVar) {
        c(new d(this, aVar));//d是个Runnable类型
    }
    private final void c(a aVar) {
        d().post(aVar);
    }

    private final Handler d() {
        Handler handler;
        synchronized (a) {
            if (!a.containsKey(this.d)) {
                HandlerThread handlerThread = new HandlerThread(this.d, 10);
                handlerThread.start();
                a.put(this.d, new Handler(handlerThread.getLooper()));
            }
            handler = (Handler) a.get(this.d);
        }
        return handler;
    }

8.所以这个就是直接运行d类

package com.google.android.play.core.a;

final class d extends a {
    private final /* synthetic */ a a;
    private final /* synthetic */ b b;

    d(b bVar, a aVar) {
        this.b = bVar;
        this.a = aVar;
    }

    public final void b() {
        this.b.b(this.a);
    }
}

9.先看看父类a

package com.google.android.play.core.a;

import com.google.android.play.core.tasks.i;

public abstract class a implements Runnable {
    private final i<?> a;

    a() {
        this.a = null;
    }

    public a(i<?> iVar) {
        this.a = iVar;
    }

    final i<?> a() {
        return this.a;
    }

    protected abstract void b();

    public final void run() {
        try {
            b();//这里调用的就是子类的b方法
        } catch (Exception e) {
            if (this.a != null) {
                this.a.a(e);
            }
        }
    }
}

10.所以b方法的代码调用到了

com.google.android.play.core.a.b.class

    private final void b(a aVar) {
        if (this.l == null && !this.f) {
            this.c.a("Initiate binding to the service.", new Object[0]);
            this.e.add(aVar);
            this.k = new h();
            this.f = true;
            if (!this.b.bindService(this.g, this.k, 1)) {
                this.c.a("Failed to bind to the service.", new Object[0]);
                this.f = false;
                for (a a : this.e) {
                    i a2 = a.a();
                    if (a2 != null) {
                        a2.a(new k());
                    }
                }
                this.e.clear();
            }
        } else if (this.f) {
            this.c.a("Waiting to bind to the service.", new Object[0]);
            this.e.add(aVar);
        } else {
            aVar.run();
        }
    }

在第六步中,卸载的话构建的 new n()进入

final class n extends a {
    private final /* synthetic */ List a;
    private final /* synthetic */ i b;
    private final /* synthetic */ k c;

    n(k kVar, i iVar, List list, i iVar2) {
        this.c = kVar;
        this.a = list;
        this.b = iVar2;
        super(iVar);
    }

    protected final void b() {
        try {
            ((com.google.android.play.core.splitinstall.a.a) this.c.a.b()).b(this.c.e, k.c(this.a), k.e(), new u(this.c, this.b));
        } catch (Throwable e) {
            k.b.a(e, "deferredUninstall(%s)", this.a);
            this.b.a(new RuntimeException(e));
        }
    }
}

看看b方法的参数,

this.c.e//第六步提到过的应用报名

k.c(this.a)//第六步提到的bundle 列表,

k.e()  //bundle 代码中写死的

new u(this.c, this.b)//这是个binder,真正可以通信的类

在第六步中,安装的话构建的 new m()进入

~~~~~~~~~~~~~~~~~~~~~~~~~~~~中间省略N部逻辑

直接到binder通信的地方:

package com.google.android.play.core.splitinstall.a;

import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.android.a.a;
import java.util.List;

public final class c extends a implements a {
    c(IBinder iBinder) {
        super(iBinder, "com.google.android.play.core.splitinstall.protocol.ISplitInstallService");
    }

    public final void a(String str, int i, Bundle bundle, d dVar) {
        Parcel a = a();
        a.writeString(str);
        a.writeInt(i);
        com.google.android.a.c.a(a, (Parcelable) bundle);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(4, a);
    }

    public final void a(String str, int i, d dVar) {
        Parcel a = a();
        a.writeString(str);
        a.writeInt(i);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(5, a);
    }

    public final void a(String str, d dVar) {
        Parcel a = a();
        a.writeString(str);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(6, a);
    }

    public final void a(String str, List<Bundle> list, Bundle bundle, d dVar) {
        Parcel a = a();
        a.writeString(str);
        a.writeTypedList(list);
        com.google.android.a.c.a(a, (Parcelable) bundle);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(2, a);
    }

    public final void b(String str, List<Bundle> list, Bundle bundle, d dVar) {
        Parcel a = a();
        a.writeString(str);
        a.writeTypedList(list);
        com.google.android.a.c.a(a, (Parcelable) bundle);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(7, a);
    }

    public final void c(String str, List<Bundle> list, Bundle bundle, d dVar) {
        Parcel a = a();
        a.writeString(str);
        a.writeTypedList(list);
        com.google.android.a.c.a(a, (Parcelable) bundle);
        com.google.android.a.c.a(a, (IInterface) dVar);
        a(8, a);
    }
}

下面到Google play代码里:

package com.google.android.play.core.d.a;

import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import com.google.android.a.c;
import java.util.List;

public abstract class b extends com.google.android.a.b implements a {
    public b() {
        super("com.google.android.play.core.splitinstall.protocol.ISplitInstallService");
    }

    protected boolean dispatchTransaction(int i, Parcel parcel, Parcel parcel2, int i2) {
        c cVar = null;
        String readString;
        List createTypedArrayList;
        Bundle bundle;
        IBinder readStrongBinder;
        IInterface queryLocalInterface;
        int readInt;
        IInterface queryLocalInterface2;
        c eVar;
        IBinder readStrongBinder2;
        switch (i) {
            case 2:
                readString = parcel.readString();
                createTypedArrayList = parcel.createTypedArrayList(Bundle.CREATOR);
                bundle = (Bundle) c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    if (queryLocalInterface instanceof c) {
                        cVar = (c) queryLocalInterface;
                    } else {
                        cVar = new e(readStrongBinder);
                    }
                }
                a(readString, createTypedArrayList, bundle, cVar);
                break;
            case 3:
                readString = parcel.readString();
                readInt = parcel.readInt();
                bundle = (Bundle) c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    cVar = queryLocalInterface instanceof c ? (c) queryLocalInterface : new e(readStrongBinder);
                }
                a(readString, readInt, bundle, cVar);
                break;
            case 4:
                readString = parcel.readString();
                readInt = parcel.readInt();
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface2 = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder);
                } else {
                    eVar = null;
                }
                a(readString, readInt, eVar);
                break;
            case 5:
                readString = parcel.readString();
                readInt = parcel.readInt();
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface2 = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder);
                } else {
                    eVar = null;
                }
                c(readString, readInt, eVar);
                break;
            case 6:
                readString = parcel.readString();
                readStrongBinder2 = parcel.readStrongBinder();
                if (readStrongBinder2 != null) {
                    queryLocalInterface2 = readStrongBinder2.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder2);
                } else {
                    eVar = null;
                }
                c(readString, eVar);
                break;
            case 7:
                readString = parcel.readString();
                createTypedArrayList = parcel.createTypedArrayList(Bundle.CREATOR);
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface2 = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder);
                } else {
                    eVar = null;
                }
                b(readString, createTypedArrayList, eVar);
                break;
            case 8:
                readString = parcel.readString();
                createTypedArrayList = parcel.createTypedArrayList(Bundle.CREATOR);
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface2 = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder);
                } else {
                    eVar = null;
                }
                a(readString, createTypedArrayList, eVar);
                break;
            case 9:
                readString = parcel.readString();
                readInt = parcel.readInt();
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder = parcel.readStrongBinder();
                if (readStrongBinder != null) {
                    queryLocalInterface2 = readStrongBinder.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder);
                } else {
                    eVar = null;
                }
                b(readString, readInt, eVar);
                break;
            case 10:
                readString = parcel.readString();
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder2 = parcel.readStrongBinder();
                if (readStrongBinder2 != null) {
                    queryLocalInterface2 = readStrongBinder2.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder2);
                } else {
                    eVar = null;
                }
                b(readString, eVar);
                break;
            case 11:
                readString = parcel.readString();
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder2 = parcel.readStrongBinder();
                if (readStrongBinder2 != null) {
                    queryLocalInterface2 = readStrongBinder2.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder2);
                } else {
                    eVar = null;
                }
                d(readString, eVar);
                break;
            case 12:
                readString = parcel.readString();
                c.a(parcel, Bundle.CREATOR);
                readStrongBinder2 = parcel.readStrongBinder();
                if (readStrongBinder2 != null) {
                    queryLocalInterface2 = readStrongBinder2.queryLocalInterface("com.google.android.play.core.splitinstall.protocol.ISplitInstallServiceCallback");
                    eVar = queryLocalInterface2 instanceof c ? (c) queryLocalInterface2 : new e(readStrongBinder2);
                } else {
                    eVar = null;
                }
                a(readString, eVar);
                break;
            default:
                return false;
        }
        return true;
    }
}

中间的代码实在是太不好查找了,

但感觉最终安装位置应该是在:

com.google.android.finsky.realtimeinstaller.q

    final synchronized void a(String str, ac acVar, int i) {
        if (this.f != null) {
            throw new IllegalStateException("This session has already been prepared");
        }
        this.d.set(false);
        PackageInstaller packageInstaller = this.a.getPackageManager().getPackageInstaller();
        int sessionParams = new SessionParams(i);
        sessionParams.setInstallAsInstantApp(this.e);
        sessionParams.setDontKillApp(true);
        sessionParams.setAppPackageName(str);
        try {
            c.a("createSession");
            sessionParams = packageInstaller.createSession(sessionParams);
            packageInstaller.registerSessionCallback(new r(this, sessionParams, str, acVar), new Handler(Looper.getMainLooper()));
            c.a("openSession");
            packageInstaller = packageInstaller.openSession(sessionParams);
            this.f = packageInstaller;
        } catch (Throwable th) {
            packageInstaller = th;
        } finally {
            c.a();
        }
    }
    final synchronized void b() {
        if (this.f == null) {
            throw new IllegalStateException("prepare() was not called on this session");
        }
        this.b.b(1656);
        PendingIntent broadcast = PendingIntent.getBroadcast(this.a, 0, new Intent("com.google.finsky.instantapps.INSTALL_COMMIT"), 134217728);
        this.a.registerReceiver(new s(broadcast), new IntentFilter("com.google.finsky.instantapps.INSTALL_COMMIT"));
        this.f.commit(broadcast.getIntentSender());
        this.f.close();
        this.b.b(1646);
        this.f = null;
    }

为什么这么推测呢?因为这代码实在是太像了,

Google Play的实现原理肯定也是采用split apk的安装方式。

我通过adb测试结果是这样的路径可以达到安装split apk的目的:

wudi:splits xiepengchong$ adb push after_sign.apk /data/local/tmp/0_after_sign.apk
10063 KB/s (1683008 bytes in 0.163s)
wudi:splits xiepengchong$ adb shell pm install-create -r -p com.google.android.samples.dynamicfeatures.ondemand
Success: created install session [899975016]
wudi:splits xiepengchong$ adb shell pm install-write 899975016 0_after_sign.apk /data/local/tmp/0_after_sign.apk
Success: streamed 1683008 bytes
wudi:splits xiepengchong$ adb shell pm install-commit 899975016

而上面的google play代码中,能实现创建session,写session与commit的只有这块代码,还有一块应该是卸载的地方。

猜你喜欢

转载自blog.csdn.net/u010479969/article/details/81261040
今日推荐