¿Cómo iniciar la aplicación Android App de interpretación del código fuente?

prefacio

Como desarrollador de Android durante muchos años, he escrito muchas aplicaciones, pero ¿cómo comienza una aplicación? Si dices que el escritorio se inicia con un clic, es correcto. Pero, ¿qué pasa con su proceso de inicio? Con tales preguntas, aprendamos paso a paso.

Proceso de arranque de Android

En general, en cualquier plataforma, los siguientes componentes se cargan y ejecutan de forma incremental:

  • cargador de arranque
  • U-bota (opcional)
  • Núcleo
  • Androide

Los procesos de Android tienen el siguiente orden:

  • En eso
  • Cigoto
  • Servidor del sistema
  • Supervisor
  • Otros demonios y procesos
  • Aplicaciones

La situación específica es la siguiente, y es interesante combinar estas dos imágenes:

imagen.png

  • ROM de arranque : cuando se presiona el botón de encendido, el código del chip de arranque comenzará a ejecutarse desde un lugar predefinido (solidificado en la ROM), cargará el programa de arranque BootLoader en la RAM y luego se ejecutará. (Este paso está diseñado e implementado por el "fabricante del chip")

  • Bootloader : Bootloader comienza a ejecutarse, en primer lugar, se encarga de completar la inicialización del hardware y arrancar el sistema operativo para iniciar. (Este paso está diseñado e implementado por el "fabricante del equipo")

  • Kernel : El kernel de Linux es el núcleo de Android, responsable de la creación de procesos, la comunicación entre procesos, los controladores de dispositivos, la gestión del sistema de archivos, etc. Android aplica parches personalizados en el núcleo principal para admitir ciertas funciones necesarias para que Android se ejecute, como wakelocks. Los núcleos se pueden cargar como imágenes sin comprimir o comprimidas. Al cargar, monta el sistema de archivos raíz (generalmente se pasa como un argumento de línea de comando del núcleo) e inicia la primera aplicación en el espacio del usuario . (Este paso es lo que debe estar involucrado en el proceso de desarrollo del kernel de Android)

  • Android : el sistema Android y las principales distribuciones de Linux, su kernel de Linux, parte del proceso de arranque es similar, la mayor diferencia entre ellos es la diferencia en el programa de inicio, porque el programa de inicio determina el sistema durante el proceso de inicio, qué sucederá ¿Qué demonios? y se inician los servicios, y qué tipo de interfaz de usuario se presenta.

Por lo tanto, el programa init es el programa más básico para analizar el proceso de inicio de Android.

  • init e init.rc : la primera aplicación de espacio de usuario que se ejecuta cuando se inicia el kernel es el ejecutable init ubicado en la carpeta raíz. El proceso analiza una secuencia de comandos de inicio denominada secuencia de comandos "init.rc". Esto está escrito en un lenguaje diseñado para que Android inicie todos los procesos, demonios y servicios necesarios para que Android funcione correctamente. Proporciona varios tipos de tiempos de ejecución, como inicio temprano, en el arranque, en post-fs, etc. (el creador del espacio de usuario)

  • Demonios y servicios : el proceso init crea varios demonios y procesos, como rild, vold, mediaserver, adb, etc., cada proceso es responsable de sus propias funciones. Una descripción de estos procesos está más allá del alcance de este artículo. En su lugar, hablaremos más sobre el proceso "Zygote".

  • Administrador de servicios : el proceso Administrador de servicios administra todos los servicios que se ejecutan en el sistema. Cada servicio creado se registra en este proceso y esta información es para referencia futura de otros procesos/aplicaciones.

  • Zygote : Zygote es uno de los primeros procesos de inicio creados al inicio. El término "cigoto" se basa en la "formación biológica de una división celular inicial para producir descendencia". De manera similar, "zygote in android" inicializa la VM de Dalivik (ART) y se bifurca para crear múltiples instancias para admitir cada proceso de Android. Facilita el uso de código compartido entre instancias de VM, lo que reduce el uso de memoria y el tiempo de carga, lo que lo hace ideal para sistemas integrados. Además de instalar un oyente en el socket del servidor, Zygote también precarga clases y recursos para su uso posterior en la aplicación de Android. Una vez finalizado, se inicia el servidor del sistema.

  • System Server : el proceso SystemServer inicia todos los servicios disponibles en Android.

En este artículo, nos enfocamos en comenzar desde init hasta el inicio de la aplicación.

1. ¿Qué es el cigoto?

En el sistema Android, cigoto es el nombre de un proceso. Android se basa en el sistema Linux. Cuando su teléfono está encendido, se iniciará un proceso llamado "init" después de que se cargue el kernel de Linux. En el sistema Linux, todos los procesos están bifurcados por el proceso init , y nuestro proceso zygote no es una excepción.

Zygote es un proceso de máquina virtual y una incubadora de instancias de máquinas virtuales. Siempre que el sistema solicite ejecutar una aplicación de Android, Zygote bifurcará (dividirá) un proceso secundario para ejecutar la aplicación.

1.1 aplicación_principal.cpp

frameworks/base/cmds/app_process/app_main.cpp

app_main.cpp se ejecuta después de que se inicia Zygote. Ya sea C/c++/java, su entrada es main(), al igual que cuando vemos Actividad, buscamos directamente el método onCreate().

1.1.1 principal()

int main(int argc, char* const argv[])
{
    ...
    //注释1:初始化AppRuntime(AndroidRunTime)
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        //注释2:设置zygote模式
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 
        ...
    }
    Vector<String8> args;
    if (!className.isEmpty()) {
        ...
    } else {
        // 我们处于 zygote 模式。
        maybeCreateDalvikCache();

        // 注释3:在 zygote 模式下,将参数传递给 ZygoteInit.main() 方法。
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        //PROP_VALUE_MAX = 92;
        char prop[PROP_VALUE_MAX];
        ...
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }    
    if (zygote) {
        //注释4:调用 AndroidRuntime.start() 方法
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        ...
    } else {
        ...
    }
}

Nota 1: Inicialice AppRuntime, que en realidad es AndroidRuntime (ART).

Nota 2: Configure el modo cigoto.

Nota 3: Pase parámetros al método ZygoteInit.main().

Nota 4: Inicie ZygoteInit. ZygoteInit aquí está la clase de inicio del proceso zygote. Esto se menciona a continuación. Veamos primero el método start() de AndroidRuntime.

1.2 AndroidRuntime.cpp

frameworks/base/core/jni/AndroidRuntime.cpp

maquina virtual android

1.2.1 inicio()

/*
 * Start the Android runtime.  This involves starting the virtual machine and calling the "static void main(String[] args)" method in the class named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //注释1:启动虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    //注释2:注册安卓功能(JNI)
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    ...
    /*
     * 启动虚拟机。 该线程成为VM的主线程,直到VM退出才会返回。
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ...
    } else {
        ...
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ...
        } else {
            //注释3
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
        }
    }
    ...
}
复制代码

Nota 1: Inicie la VM (Máquina Virtual)

Nota 2: Registro de funciones de Android (JNI)

Nota 3: utilice JNI para llamar al método main() de Zygotelnit. Zygotelnit aquí es un archivo de clase, es decir, ingresa al campo java desde aquí.

JNI: un puente que conecta la capa nativa (C/C++) y la capa Java.

1.3 ZygoteInit.java

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/**
 * zygote 进程的启动类。
 */
public class ZygoteInit {
    ...
}
复制代码

Este es el punto de entrada para el proceso Zygote. Crea servicios de Zygote, carga recursos y maneja otras tareas relacionadas con el proceso de preparación para la bifurcación en una aplicación.

1.3.1 principal()

    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        try {
            ...
            boolean startSystemServer = false;
            //argv:用于指定 Zygote 配置的命令行参数。
            ...
            if (!enableLazyPreload) {
                //注释1:预加载资源。
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }
            ...
            //注释2:创建Zygote 的 LocalServerSocket 。
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                //注释3:开始fork我们的SystemServer进程。
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                ...
            }
            ...
            // 注释4:zygote 永久循环。
            caller = zygoteServer.runSelectLoop(abiList);            
        } catch (Throwable ex) {
            ...
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        ...
    }
复制代码

Nota 1: recursos de precarga.

Nota 2: Cree el LocalServerSocket de Zygote.

Nota 3: Comience a bifurcar nuestro proceso SystemServer.

Nota 4: bucles de cigoto para siempre.

Aquí vemos forkSystemServer();

1.3.2 forkSystemServer ()

    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        //命令行来启动SystemServer
        //ZygoteInit.main(String argv[])里面的argv 跟这个类似
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        //处理与 zygote spawner 相关的 args 的参数解析。
        ZygoteArguments parsedArgs;
        int pid;
        try {
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            commandBuffer.close();
            ...

            //请求 fork 系统服务器进程
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
复制代码

Aquí se inicia un servidor del sistema. Echemos un vistazo a él a continuación.

2, servidor del sistema

El servidor del sistema también es SystemServer. SystemServer también es un proceso, que incluye 92 servicios como ActivityTaskManagerService, ActivityManagerService, PackageManagerService y WindowManagerService.

Hay dos procesos muy importantes en Android Framework:

  • Proceso del servidor del sistema.

  • Proceso de cigoto.

2.1 SystemServer.java

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer {
    ...
}
复制代码

2.1.1 principal()

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
        ...
    }    
复制代码

Echemos un vistazo a lo que se usa en run ()?

2.1.2 ejecutar()

    private void run() {
        try {
            ...
            // 注释1:加载动态库libandroid_service.so。
            System.loadLibrary("android_servers");

            // 注释2:创建系统上下文。
            createSystemContext();

            // 调用每个进程的主线模块初始化。
            ActivityThread.initializeMainlineModules();

            // 注释3:创建 SystemServiceManager。
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // 为可并行化的 init 任务准备线程池
            SystemServerInitThreadPool.start();
            ...
        } finally {

        }
        // 注释4:Start services。
        try {
            //下面咱们看看这个三个方法启动什么服务
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            ...
        } finally {
            t.traceEnd(); // StartServices
        }

        ...
        // 注释5:Loop 永久循环。
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

复制代码

Nota 1: Cargue la biblioteca dinámica libandroid_service.so.

Nota 2: Cree un contexto de sistema.

Nota 3: Cree SystemServiceManager.

Nota 4: servicios de inicio (startBootstrapServices, startCoreServices, startOtherServices)

Nota 5: Loop loops para siempre.

2.1.3 crearContextodelSistema()

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
复制代码

Inicialice el objeto de contexto del sistema mSystemContext y establezca el tema predeterminado, mSystemContext es en realidad un objeto de contexto (ContextImpl).

Cuando se llama a ActivityThread.systemMain(), se llama a ActivityThread.attach(true), y en added(), se crea el objeto Aplicación y se llama a Application.onCreate().

2.1.4 iniciarBootstrapServices()

    /**
     * 启动系统引导服务,因为这些服务之间有复杂的相互依赖关系,所以都放在了这个方法里面。
     */
    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        ...
        final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
        SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);

        // PlatformCompat Service 由 ActivityManagerService, PackageManagerService 和 其他服务做使用
        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
                new PlatformCompatNative(platformCompat));
        AppCompatCallbacks.install(new long[0]);

        mSystemServiceManager.startService(FileIntegrityService.class);
        Installer installer = mSystemServiceManager.startService(Installer.class);
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
        startMemtrackProxyService();

        // StartActivityManager
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        //初始化 ActivityManagerService
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();

        mDataLoaderManagerService = mSystemServiceManager.startService(
                DataLoaderManagerService.class);

        mIncrementalServiceHandle = startIncrementalService();
        t.traceEnd();

        //初始化PowerManagerService(电源服务),需要提前启动,因为其他服务需要它。
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        mSystemServiceManager.startService(ThermalManagerService.class);

        // 电源管理已经开启,ActivityManagerService负责电源管理功能
        mActivityManagerService.initPowerManagement();

        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
        ...

        mSystemServiceManager.startService(LightsService.class);

        // Package manager isn't started yet; need to use SysProp not hardware feature
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }

        // 初始化DisplayManagerService(显示管理器)
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // Start the package manager.
        try {
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        } finally {

        }

        // 现在PackageManagerService已经启动,注册 dex 加载报告器来捕获系统服务加载的任何 dex 文件。
        // 这些 dex 文件将由 BackgroundDexOptService 优化。
        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        ...
        //将AMS等添加到ServiceManager中
        mActivityManagerService.setSystemProcess();
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {

                } finally {
                }
            }
        }

        ...
        mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
            TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
            startSensorService();
        }, START_SENSOR_SERVICE);

        // startBootstrapServices
    }
复制代码

Cambios principales:

  • ActivityTaskManagerService(ATMS): responsable de la gestión de actividades y procesos, incluido el ciclo de vida y el cambio de estado.

  • ActivityManagerService (AMS): una subclase de AMN, responsable de administrar tres componentes principales (excepto Actividad) y procesos, incluido el ciclo de vida y el cambio de estado. AMS es extremadamente complejo porque tiene que interactuar con la interfaz de usuario, involucrando ventanas.

ActivityTaskManagerService: generado al eliminar el contenido relacionado con la actividad de ActivityManagerService.

PowerManagerService(PMS): servicio de administración de energía.

PackageManagerService(PKMS): El servicio de administración de paquetes, no llamado PMS, es para distinguirlo del servicio de administración de energía.

2.1.5 startCoreServices()

    /**
     * 启动核心服务。
     */
    private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
        // Service for system config
        mSystemServiceManager.startService(SystemConfigService.class);
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        ...
        mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);

        mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);

        mSystemServiceManager.startService(NativeTombstoneManagerService.class);

        mSystemServiceManager.startService(BugreportManagerService.class);

        mSystemServiceManager.startService(GpuService.class);

        // startCoreServices
    }

复制代码

2.1.6 iniciarOtrosServicios()

    /**
     * 启动其他服务。
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

        final Context context = mSystemContext;
        VibratorService vibrator = null;
        DynamicSystemService dynamicSystem = null;
        IStorageManager storageManager = null;
        NetworkManagementService networkManagement = null;
        IpSecService ipSecService = null;
        VpnManagerService vpnManager = null;
        VcnManagementService vcnManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        NsdService serviceDiscovery = null;
        WindowManagerService wm = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        MmsServiceBroker mmsService = null;
        HardwarePropertiesManagerService hardwarePropertiesService = null;
        PacProxyService pacProxyService = null;
        ...
        // 现在便可以开始启动三方APP应用(如Launcher启动桌面)
        mActivityManagerService.systemReady(() -> {
        ...
         }, t);       
        // startOtherServices
    }
复制代码

Después de los pasos anteriores, cuando llamamos a createSystemContext() para crear el contexto del sistema, hemos completado la creación de mSystemContext y ActivityThread.

Se han creado objetos como ATMS, AMS, WMS y PKMS y se han inicializado las variables miembro.

Nota: Este es el proceso cuando se inicia el proceso del sistema.Después de eso, se iniciará el sistema.

El programa Launcher completa la carga y visualización de la interfaz del sistema.

En el diseño del marco de Android, el lado del servidor se refiere a los servicios del sistema compartidos por todas las aplicaciones, como ATMS, AMS, WMS, PKMS, etc., que mencionamos aquí. Estos servicios básicos del sistema son compartidos por todas las aplicaciones.

3. ¿Qué es el lanzador?

En el sistema Android, el Lanzador inicia la aplicación. De hecho, el Lanzador en sí también es una aplicación . Después de instalar otras aplicaciones, aparecerá el icono correspondiente en la interfaz del Lanzador. Cuando se hace clic en este icono, el Lanzador se inicia la aplicación correspondiente.

Por supuesto, también puede iniciar aplicaciones en otras aplicaciones. Pero en esencia llama a startActivity().

3.1 LauncherActivity.java

frameworks/base/core/java/android/app/LauncherActivity.java

/**
 * Displays a list of all activities which can be performed
 * for a given intent. Launches when clicked.
 *
 * @deprecated Applications can implement this UI themselves using
 *   {@link androidx.recyclerview.widget.RecyclerView} and
 *   {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)}
 */
@Deprecated
public abstract class LauncherActivity extends ListActivity {
    ...
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }
}
复制代码

resumen

Se adjunta imagen completa

Si conoce startActivity(), puede echar un vistazo directamente. Hay tanto contenido en esta publicación que me irrita solo mirarla. Si no lo ha visto, tome una ola, y los detalles se explicarán en el siguiente artículo: ❤️ Análisis del código fuente de Android startActivity ❤️.

Supongo que te gusta

Origin blog.csdn.net/ajsliu1233/article/details/120711444
Recomendado
Clasificación