Entrada de base cero de Android | mecanismo de transmisión Transmisión

inserte la descripción de la imagen aquí

Las aplicaciones de Android pueden recibir o enviar mensajes desde el sistema u otras aplicaciones mediante transmisión. Similar al patrón de diseño suscribirse-publicar. Se pueden emitir transmisiones cuando ocurren ciertos eventos. El sistema transmite cuando cambia algún estado, como encendido o carga. La aplicación también puede enviar transmisiones personalizadas. La radiodifusión se puede utilizar para la comunicación entre aplicaciones y es una forma de IPC.

tipo de transmisión

El tipo de transmisión también puede considerarse como un atributo de la transmisión.

  • Las transmisiones estándar (transmisiones normales) son transmisiones completamente asíncronas. Una vez enviada la transmisión, todos los receptores de la transmisión la reciben casi simultáneamente. Diferentes aplicaciones pueden registrarse y recibir transmisiones estándar. Por ejemplo, transmisión del sistema.
  • Las transmisiones ordenadas (transmisiones ordenadas) se transmiten de forma sincrónica. Sólo un receptor de transmisión puede recibir esta transmisión a la vez. La transmisión no continuará entregándose hasta que este receptor haya sido procesado. Las transmisiones ordenadas son transmisiones globales.
  • Las transmisiones locales (Local Broadcasts) son únicamente transmisiones enviadas y recibidas por esta App. Los receptores registrados para transmisiones locales no pueden recibir transmisiones estándar.
  • Transmisiones autorizadas Puede tener permisos relevantes al enviar transmisiones, y solo la aplicación o el receptor de transmisiones que ha solicitado permisos puede recibir las transmisiones autorizadas correspondientes. Si se solicita el permiso correspondiente en el manifiesto, el receptor puede recibir la transmisión correspondiente sin solicitar otro permiso.

recibir transmisión

Para crear un receptor de transmisión y llamar onReceive()a un método, se requiere una clase que herede BroadcastReceiver.

El registro en código de transmisión se denomina registro dinámico. El registro AndroidManifest.xmlse llama registro estático. Los receptores de ondas rígidas registrados dinámicamente deben estar dados de baja. onDestroy()Llame al método in para unregisterReceiver()cancelar el registro.

No onReceive()agregue demasiadas operaciones lógicas ni operaciones que requieran mucho tiempo al método. Debido a que no está permitido abrir subprocesos en el receptor de transmisión, cuando onReceive()el método se ejecuta durante mucho tiempo sin finalizar, el programa informará un error. Por lo tanto, los receptores de transmisión generalmente se usan para abrir otros componentes, como crear una notificación en la barra de estado o iniciar un servicio.

Cree un nuevo MyExampleReceiver heredado de BroadcastReceiver .

public class MyExampleReceiver extends BroadcastReceiver {
    
    
    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        Toast.makeText(context,"Got it",Toast.LENGTH_SHORT).show();
        //abortBroadcast();
    }
}

abortBroadcast()la transmisión ordenada se puede truncar

AndroidManifest.xmlRegistre el receptor de transmisión; complete android:nameel nombre del receptor. La prioridad del receptor de transmisión se puede configurar:

<intent-filter android:priority="100">

<receiver android:name=".MyExampleReceiver">
    <intent-filter>
        <action android:name="com.rust.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

Deje que el receptor reciba una "com.rust.broadcasttest.MY_BROADCAST"transmisión. Este valor se pasa al enviar transmisiones personalizadas (transmisiones estándar). Por ejemplo:

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);

Para enviar una transmisión ordenada, debe llamarsendOrderedBroadcast()

Intent intent = new Intent("com.rust.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);

enviar transmisión

La aplicación tiene 3 formas de enviar transmisiones. Enviar una transmisión requiere el uso de la clase Intent .

enviarOrderedBroadcast(Intención, Cadena)

Enviar una transmisión ordenada. Sólo 1 receptor de transmisión puede recibir la transmisión a la vez. Después de que un receptor recibe una transmisión ordenada, puede truncar la transmisión por completo o pasar cierta información al siguiente receptor. El orden de las transmisiones ordenadas puede verse android:priorityafectado por las etiquetas. El orden en el que los receptores del mismo nivel reciben las emisiones es aleatorio.

enviarBroadcast(Intención)

Envía transmisiones a todos los receptores en un orden indefinido. También conocida como radiodifusión general. Este método es más eficiente, pero el receptor no puede pasar el mensaje al siguiente receptor. Estas transmisiones tampoco se pueden truncar.

**LocalBroadcastManager.sendLa transmisión de transmisión solo se puede entregar dentro de la aplicación, y los receptores de transmisión solo pueden recibir transmisiones desde esta aplicación. Este método es más eficiente que la transmisión global (sin comunicación entre procesos, IPC) y no hay necesidad de preocuparse de que otras aplicaciones reciban su transmisión y otros problemas de seguridad.

Difusión y permisos

Enviar una transmisión con permisos

Cuando llamas sendBroadcast(Intent, String)o sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle), puedes especificar un permiso. El receptor sólo podrá recibir esta emisión cuando haya solicitado el permiso correspondiente en el manifiesto.

Por ejemplo, enviar una transmisión con permisos.

sendBroadcast(new Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS);

Las apps que reciben retransmisiones deben registrarse con los permisos correspondientes

<uses-permission android:name="android.permission.SEND_SMS"/>

Por supuesto, también puedes utilizar personalizado. Utilice la etiqueta de permiso en el manifiesto

<permission android:name="custom_permission" />

Compílelo después de agregarlo. puede ser llamadoManifest.permission.custom_permission

Recibir transmisiones con permisos

Si se declaran permisos al registrar un receptor de transmisión, solo se recibirán transmisiones con los permisos correspondientes.

Declare permisos en el archivo de configuración para que el programa pueda acceder a cierta información clave. Por ejemplo, permite consultar el estado de la red del sistema.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<!-- 机器开机广播 -->
<uses-permission android:name="android.permission.BOOT_COMPLETED">

Si no se solicita permiso, el programa puede cerrarse inesperadamente.

Ejemplo de uso

Enviar y recibir transmisiones. Se divide en dos Apps, la del remitente y la del receptor.

Utilice transmisiones autorizadas. Permisos del sistema y permisos personalizados. Los permisos deben declararse en AndroidManifest.xml . Si se trata de un permiso personalizado, primero debe agregar el permiso personalizado.

<!-- 自定义的权限  给广播用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />

Traiga la declaración de permiso al enviar la transmisión. La parte receptora (ya sea su propia aplicación o no) debe AndroidManifest.xmlsolicitar permiso en formato . También es necesario declarar los permisos al registrar un receptor.

Enviar transmisión ordenada sin privilegios

Intent intent = new Intent(MSG_PHONE);
sendOrderedBroadcast(intent, null);
Log.d(TAG, "[RustFisher-App1] 发送不带权限的有序广播, " + intent.getAction());

Código de aplicación 1 del remitente

private static final String TAG = "rustApp";
    public static final String MSG_PHONE = "msg_phone";
    public static final String PERMISSION_RUST_1 = "com.rust.permission_rust_1";

        // onCreate注册广播接收器
        registerReceiver(mStandardReceiver1, makeIF());
        registerReceiver(mStandardReceiver2, makeIF());
        registerReceiver(mStandardReceiver3, makeIF());

        registerReceiver(mStandardReceiverWithPermission, makeIF(),
                Manifest.permission.permission_rust_1, null);  // 带上权限

        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver1, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver2, makeIF());
        LocalBroadcastManager.getInstance(getApplicationContext())
                .registerReceiver(mLocalReceiver3, makeIF());

        // 解除接收器
        unregisterReceiver(mStandardReceiver1);
        unregisterReceiver(mStandardReceiver2);
        unregisterReceiver(mStandardReceiver3);

        unregisterReceiver(mStandardReceiverWithPermission);

        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver1);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver2);
        LocalBroadcastManager.getInstance(getApplicationContext())
                .unregisterReceiver(mLocalReceiver3);

    // 发送标准广播
    private void sendStandardBroadcast() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送标准广播");
    }

    // 发送带权限的标准广播
    private void sendStandardBroadcastWithPermission() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        sendBroadcast(intent, PERMISSION_RUST_1);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送带权限的标准广播");
    }

    // 发送本地广播
    private void sendAppLocalBroadcast() {
    
    
        Intent intent = new Intent(MSG_PHONE);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
        Log.d(TAG, "[RustFisher-App1] Dispatcher 发送本地广播");
    }

    private IntentFilter makeIF() {
    
    
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver1 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器1 收到: " + intent.getAction());
        }
    };

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver2 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器2 收到: " + intent.getAction());
            if (intent.getAction().endsWith(MSG_PHONE)) {
    
    
                abortBroadcast(); // 截断有序广播
                Log.d(TAG, "[RustFisher-App1] 标准接收器2截断有序广播 " + intent.getAction());
            }
        }
    };

    // 标准接收器  用context来注册
    private BroadcastReceiver mStandardReceiver3 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 标准接收器3 收到: " + intent.getAction());
        }
    };

    // 注册的时候给它带权限  标准接收器
    private BroadcastReceiver mStandardReceiverWithPermission = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 带权限的标准接收器收到: " + intent.getAction());
        }
    };

    /**
 * 用LocalBroadcastManager来注册成为本地接收器
 * 收不到标准广播 - 不论是本app发出的还是别的地方发出来的
 */
    private BroadcastReceiver mLocalReceiver1 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器1 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver2 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器2 收到: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver3 = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[RustFisher-App1] 本地接收器3 收到: " + intent.getAction());
        }
    };

Código App2 del receptor

<!-- 自定义的权限  给广播用 -->
<permission android:name="com.rust.permission_rust_1" />
<uses-permission android:name="com.rust.permission_rust_1" />
public static final String MSG_PHONE = "msg_phone";

    // onCreate里注册接收器
    registerReceiver(mDefaultReceiver, makeIF());
    LocalBroadcastManager.getInstance(getApplicationContext())
            .registerReceiver(mLocalReceiver, makeIF());

    unregisterReceiver(mDefaultReceiver);
    LocalBroadcastManager.getInstance(getApplicationContext())
            .unregisterReceiver(mLocalReceiver);

    private BroadcastReceiver mDefaultReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[App2] standard receive: " + intent.getAction());
        }
    };

    private BroadcastReceiver mLocalReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            Log.d(TAG, "[App2] local receive: " + intent.getAction());
        }
    };

    private IntentFilter makeIF() {
    
    
        IntentFilter intentFilter = new IntentFilter(MSG_PHONE);
        intentFilter.addAction(Intent.ACTION_TIME_TICK);
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        return intentFilter;
    }

Al utilizar LocalBroadcastManagerla transmisión local enviada, otra aplicación no puede recibirla. Para recibir transmisiones locales, también necesita LocalBroadcastManagerregistrar el receptor.

Puedes pensar en la transmisión local como un sistema de transmisión parcial dentro de la aplicación.

En el experimento, notamos que Intent.ACTION_TIME_TICKla transmisión se puede truncar.

La pantalla del monitor se ilumina

Utilice la transmisión para monitorear el estado de la pantalla dentro y fuera del dispositivo. Esta es una transmisión del sistema.

La acción utilizada es

  • Intent.ACTION_SCREEN_ON pantalla brillante
  • Intent.ACTION_SCREEN_OFF función
    private void registerScreenListener() {
    
    
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(mScreenReceiver, filter);
    }

    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            final String action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) {
    
    
                // 屏幕亮
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
    
    
                // 屏幕灭
            }
        }
    };

Preguntas de entrevista relacionadas con la transmisión

1. ¿Existe un límite para los datos transmitidos por radiodifusión, cuánto es y por qué debería limitarse?

  • La transmisión consiste en transportar los datos que deben entregarse a través de Intent.
  • La intención se implementa a través del mecanismo Binder.
  • Binder tiene un límite en el tamaño de los datos, diferentes salas son diferentes, generalmente 1M

2. ¿Clasificación de la radiodifusión?

  • Transmisión estándar: se envía a todos los receptores registrados en el sistema actual a través de context.sendBroadcast o context.sendBroadcastAsUser, es decir, mientras estén registrados, la recibirán. La aplicación se utiliza cuando es necesario notificar a cada receptor de transmisión, como al iniciar.
  • Transmisión ordenada: el receptor procesa la transmisión de acuerdo con la prioridad, y el receptor que procesó previamente la transmisión puede detener la entrega de la transmisión, generalmente a través de context.sendOrderedBroadcast o context.sendOrderedBroadcastAsUser, que se utiliza en escenarios que requieren una interceptación específica, como como SMS de lista negra , interceptación telefónica.
  • Transmisión fija: se puede enviar a destinatarios registrados en el futuro, lo que significa que el sistema guardará la transmisión fija anterior en AMS. Una vez que se registre una transmisión que coincida con la transmisión fija guardada, la transmisión se recibirá inmediatamente después de que se complete el registro. completado. Generalmente, envíelo a través de context.sendStickyBroadcast o context.sendStickyOrderedBroadcast. Literalmente, se puede ver que las transmisiones fijas también se dividen en transmisiones fijas ordinarias y transmisiones fijas ordenadas.
  • Transmisión local: las transmisiones enviadas solo se pueden entregar dentro de la aplicación y los receptores de transmisiones solo pueden aceptar transmisiones desde esta aplicación.
  • Difusión global: sistema y difusión, la difusión enviada puede ser recibida por cualquier otra aplicación, y también puede recibir la difusión de cualquier otra aplicación.

3. Escenarios de uso de transmisión y métodos de uso La transmisión es un mecanismo ampliamente utilizado para transmitir información entre aplicaciones. Se utiliza principalmente para monitorear la información de transmisión enviada por el sistema o la aplicación, y luego usar la información de transmisión como un proceso lógico correspondiente. transmitir una pequeña cantidad de datos con baja frecuencia.

Al realizar servicios de arranque y cambios de estado de la red, cambios de energía, mensajes de texto y llamadas entrantes, el programa de aplicación se puede procesar en consecuencia al recibir la transmisión del sistema.

usar:

//在AndroidManifest中静态注册
<receiver
    android:name=".MyBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="100">
        <action android:name="com.example.hp.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

//动态注册,在代码中注册
@Override
protected void onCreate(Bundle savedInstanceState) {
    
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mIntentFilter = new IntentFilter();
    //添加广播想要监听的类型,监听网络状态是否发生变化
    mIntentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    mNetworkChangeReceiver = new NetworkChangeReceiver();
    //注册广播
    registerReceiver(mNetworkChangeReceiver, mIntentFilter);
}

@Override
protected void onDestroy() {
    
    
    super.onDestroy();
    //取消注册广播接收器
    unregisterReceiver(mNetworkChangeReceiver);
}

//发送广播,同样通过Intent
Intent intent = new Intent("com.example.hp.broadcasttest.MY_BROADCAST");
//发送标准广播
sendBroadcast(intent);

//接收广播
public class MyBroadcastReceiver extends BroadcastReceiver {
    
    
    public MyBroadcastReceiver() {
    
    
    }

    @Override
    public void onReceive(Context context, Intent intent) {
    
    
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Toast.makeText(context, "received", Toast.LENGTH_SHORT).show();
        //将这条广播截断
//        abortBroadcast();
    }
}

4. Diferencia entre BroadcastReceiver y LocalBroadcastReceiver Receptor de transmisión:

1)用于应用间的传递消息
(2)由于跨应用,存在安全问题

Receptor de transmisión local:

1)广播数据在本应用范围内传播。  
(2)不用担心别的应用伪造广播。  
(3)比发送全局广播更高效、安全。  
(4)无法使用静态注册  

5. Cómo registrarse y usar BroadcastReceiver en manifiesto y código (1) Regístrese estáticamente en AndroidManifest y utilícelo directamente. (2) En el código, regístrese a través de RegisterReceiver. (3) Después de registrarse y enviar, reciba y procese la transmisión en onReceive de BroadcastReceiver (un receptor personalizado hereda de BroadcastReceiver).

6. Límite de tiempo para la anr causada por la transmisión Transmisión en primer plano: BROADCAST_FG_TIMEOUT = 10 s Transmisión en segundo plano: BROADCAST_BG_TIMEOUT = 60 s

última parte

[Equipo técnico de Tencent producido] Entrada a la competencia de base cero de Android, tutorial de instalación de Android Studio + un conjunto completo de tutoriales básicos de Android

Tutorial de programación de Android

Conceptos básicos del lenguaje Java desde la entrada hasta la familiaridad

inserte la descripción de la imagen aquí

Conceptos básicos del lenguaje Kotlin desde la entrada hasta la familiaridad

inserte la descripción de la imagen aquí

Pila de tecnología Android desde la entrada hasta la familiaridad

inserte la descripción de la imagen aquí

Aprendizaje integral del depósito familiar Android Jetpack

inserte la descripción de la imagen aquí

Para los principiantes, puede resultar difícil instalar Android Studio. Puede ver el siguiente video y aprender a instalarlo y ejecutarlo paso a paso.

Tutorial de instalación de Android Studio

inserte la descripción de la imagen aquí

Con el aprendizaje de la etapa de Java, se recomienda centrarse en el aprendizaje en video en esta etapa y complementarlo con libros para verificar si hay omisiones. Si se centra en los libros, puede escribir códigos basados ​​en explicaciones de libros, complementados con vídeos didácticos para comprobar si hay omisiones. Si tiene problemas, puede ir a Baidu. Generalmente, muchas personas encontrarán problemas al comenzar y darán mejores respuestas.

Es necesario dominar puntos de conocimiento básicos, como cómo utilizar los cuatro componentes principales, cómo crear un Servicio, cómo diseñar, una Vista personalizada simple, animación, comunicación de red y otras tecnologías comunes.

Se ha preparado un conjunto completo de tutoriales de base cero para usted; si lo necesita, puede agregar el código QR a continuación para obtenerlo gratis

Un conjunto completo de tutoriales básicos de Android.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/Android23333/article/details/132445087
Recomendado
Clasificación