ลงทะเบียนเครื่องรับสัญญาณออกอากาศโดยทางโปรแกรม


149

ฉันต้องการทราบว่าวิธีปฏิบัติที่ดีที่สุดคืออะไร / วิธีการลงทะเบียนเครื่องรับสัญญาณออกอากาศโดยทางโปรแกรม ฉันต้องการลงทะเบียนตัวรับเฉพาะตามตัวเลือกของผู้ใช้

เนื่องจากการลงทะเบียนเสร็จสิ้นผ่านไฟล์ Manifest ฉันจึงสงสัยว่ามีวิธีที่เหมาะสมในการทำรหัสนี้หรือไม่


2
CoderzPassion Broadcast Recieverรายละเอียดการสอนที่ดีที่สุดเท่าที่เคยมีมา
karanatwal.github.io

โปรดอ้างอิงลิงค์ stackoverflow.com/questions/15698790/

คำตอบ:


64

ดูเหมือนว่าคุณต้องการควบคุมว่าส่วนประกอบที่เผยแพร่ในรายการของคุณเปิดใช้งานอยู่หรือไม่ไม่ลงทะเบียนผู้รับ (ผ่าน Context.registerReceiver ()) แบบไดนามิกในขณะที่ทำงานอยู่

ถ้าเป็นเช่นนั้นคุณสามารถใช้ PackageManager.setComponentEnabledSetting () เพื่อควบคุมว่าองค์ประกอบเหล่านี้ทำงานอยู่หรือไม่:

http://developer.android.com/reference/android/content/pm/PackageManager.html#setComponentEnabledSetting(android.content.ComponentName, int, int)

หมายเหตุหากคุณสนใจที่จะรับการถ่ายทอดเท่านั้นในขณะที่คุณกำลังใช้งานจะเป็นการดีกว่าที่จะใช้ registerReceiver () ส่วนประกอบตัวรับสัญญาณนั้นมีประโยชน์เป็นหลักเมื่อคุณต้องการตรวจสอบให้แน่ใจว่าแอปของคุณเปิดตัวทุกครั้งที่มีการส่งสัญญาณออกอากาศ


1
ฉลาด! คุณทำให้ฉันตรง ขอบคุณมาก ๆ
CoolStraw

เป็นคนดี - ไม่รู้ว่าคุณสามารถทำสิ่งนี้ได้ :)
Chris Noldus


1
@hackbod จะเพิ่มเมตาแท็กข้อมูลในตัวรับสัญญาณที่กำหนดเองได้อย่างไร คุณมีความคิดใด ๆ !! ฉันต้องเพิ่มเมตาดาต้าแท็กที่เราใช้ใน androidmanifest.xml
Zala Janaksinh

1
สุดยอดการสอนจนถึงวันที่coderzpassion.com/implement-broadcastreceiver-androidและในภาษาง่าย ๆ
Jagjit Singh

269

ในonCreateวิธีการของคุณคุณสามารถลงทะเบียนผู้รับเช่นนี้:

private BroadcastReceiver receiver;

@Override
public void onCreate(Bundle savedInstanceState){

  // your oncreate code should be

  IntentFilter filter = new IntentFilter();
  filter.addAction("SOME_ACTION");
  filter.addAction("SOME_OTHER_ACTION");

  receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      //do something based on the intent's action
    }
  };
     registerReceiver(receiver, filter);
}

อย่าลืมเรียกใช้ในonDestroyวิธีการ:

 @Override
 protected void onDestroy() {
  if (receiver != null) {
   unregisterReceiver(receiver);
   receiver = null;
  }
  super.onDestroy();
 }

19
ขอบคุณมันใช้งานได้ดี ในการส่งการถ่ายทอดฉันใช้รหัส Intent i = new Intent ("SOME_ACTION"); sendBroadcast (i);
Ben Clayton

7
ทำไมไม่อยู่ในประวัติย่อและเมื่อเริ่มต้น?
Syed Raza Mehdi

จะเกิดอะไรขึ้นหากฉันไม่ถอนการลงทะเบียนเครื่องรับสัญญาณออกอากาศ มันจะปล่อยให้ตัวรับสัญญาณออกอากาศลงทะเบียนแล้วหรือไม่แม้หลังจากรีบูตเครื่องหรือไม่
Jaydev

5
ไม่รับประกันว่าonDestroy()จะถูกเรียกดังนั้นการสร้างหน่วยความจำรั่วอาจเกิดขึ้น การลงทะเบียน / ยกเลิกการลงทะเบียนในonStart()/ onStop()ดีกว่า
Neria Nachum

นี่หมายความว่าฉันไม่ต้องสร้างคลาสตัวรับสัญญาณออกอากาศหรือไม่? ฉันสามารถใส่รหัส onReceive () ทั้งหมดของฉันที่นี่และมันจะทำงานได้อย่างไร
Taslim Oseni

70

Broadcast Receiverจุดหนึ่งที่สำคัญที่คนลืมที่จะกล่าวถึงเป็นครั้งหนึ่งของชีวิต ความแตกต่างของการลงทะเบียนโดยทางโปรแกรมจากการลงทะเบียนในAndroidManifest.xmlคือ ในไฟล์ Manifest ไม่ได้ขึ้นอยู่กับอายุการใช้งานของแอปพลิเคชัน ในขณะที่การลงทะเบียนโดยทางโปรแกรมจะขึ้นอยู่กับอายุการใช้งานของแอปพลิเคชัน ซึ่งหมายความว่าหากคุณลงทะเบียนในAndroidManifest.xmlคุณสามารถตรวจจับ Intent ที่ออกอากาศแม้ว่าแอปพลิเคชันของคุณจะไม่ทำงาน

แก้ไข:บันทึกย่อดังกล่าวไม่เป็นจริงอีกต่อไปในฐานะของ Android 3.1 ระบบ Android จะแยกตัวรับสัญญาณทั้งหมดจากการรับการแจ้งเตือนตามค่าเริ่มต้นหากแอปพลิเคชันที่เกี่ยวข้องไม่เคยเริ่มต้นโดยผู้ใช้หรือหากผู้ใช้หยุดแอปพลิเคชันผ่านเมนู Android อย่างชัดเจน จัดการแอปพลิเคชัน→) https://developer.android.com/about/versions/android-3.1.html

นี่เป็นคุณลักษณะด้านความปลอดภัยเพิ่มเติมเนื่องจากผู้ใช้สามารถมั่นใจได้ว่าเฉพาะแอปพลิเคชันที่เขาเริ่มต้นเท่านั้นที่จะได้รับการกระจายเนื้อหา

ดังนั้นจึงสามารถเข้าใจได้ว่าตัวรับสัญญาณที่ลงทะเบียนไว้ในแอปพลิเคชันonCreate()จะมีผลเช่นเดียวกันกับที่ประกาศในAndroidManifest.xmlจาก Android 3.1 ข้างต้น


1
นี่เป็นบันทึกที่ดี ฉันกำลังดูหนังสือที่ฉันอ่านเกี่ยวกับ Android และสงสัยว่าทำไมทั้งสองวิธีในการนำการออกอากาศมาใช้ มันดูเหมือนว่าสำหรับการย้อนกลับเข้ากันได้ แต่ฉันไม่แน่ใจ
Neon Warge

คุณจริง ๆ แล้วสิ่งที่แก้ไขเป็นจริงหรือไม่ ฉันหมายถึงประโยคสุดท้าย Android มีแนวโน้มที่จะฆ่าแอปพลิเคชันของคุณได้ตลอดเวลาซึ่งจะส่งผลให้ผู้รับที่ลงทะเบียนทางโปรแกรมของคุณไม่ทำงานอีกต่อไป แต่รายการที่ลงทะเบียนจะยังคงใช้งานได้
JacksOnF1re

40

กำหนดผู้รับสัญญาณออกอากาศได้ทุกที่ในกิจกรรม / ชิ้นส่วนดังนี้:

mReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
     Log.d(TAG," onRecieve"); //do something with intent
   }
 };

กำหนดตัวกรอง Intent ใน onCreate()

mIntentFilter=new IntentFilter("action_name");

ตอนนี้ลงทะเบียน BroadcastReciever ในonResume()และยกเลิกการลงทะเบียนในonPause()[เพราะไม่มีการใช้การออกอากาศถ้ากิจกรรมถูกหยุดชั่วคราว]

@Override
protected void onResume() {
     super.onResume();
     registerReceiver(mReceiver, mIntentFilter);
}

@Override
protected void onPause() {
    if(mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
    }
    super.onPause();
}

สำหรับรายละเอียดกวดวิชา, มีลักษณะที่ออกอากาศรับสองวิธีที่จะดำเนินการ


ตัวอย่างที่ดีที่สุดที่ฉันพบ! ขอบคุณ!
Ayush Goyal

1
@SohailAziz ลิงก์นี้ให้คำตอบที่ดี คุณสามารถใส่บริบทของลิงค์ลงในคำตอบของคุณได้ไหมถ้าลิงค์นั้นลงไปคำตอบของคุณยังคงเกี่ยวข้อง?
iRuth

ในมุมมองส่วนตัวของฉันการออกอากาศควรลงทะเบียนใน onResume และ onPause ตามที่คุณแนะนำ แต่บางคนบอกว่ามันต้องอยู่บน onCreate และ onDestroy คุณสามารถอธิบายข้อดีและข้อเสียของทั้งคู่ได้หรือไม่
Syed Raza Mehdi

2
@SyedRazaMehdi หากการออกอากาศถูกใช้เพื่ออัปเดต UI [ซึ่งโดยส่วนใหญ่แล้ว] คุณควรลงทะเบียนใน onResume และยกเลิกการลงทะเบียนใน onPause เนื่องจากการออกอากาศจะไม่ได้ผล
SohailAziz

ขอบคุณนี่คือคำตอบที่ดีที่สุด
Saeid Z

4
package com.example.broadcastreceiver;


import android.app.Activity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

   UserDefinedBroadcastReceiver broadCastReceiver = new UserDefinedBroadcastReceiver();

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

   /**
    * This method enables the Broadcast receiver for
    * "android.intent.action.TIME_TICK" intent. This intent get
    * broadcasted every minute.
    *
    * @param view
    */
   public void registerBroadcastReceiver(View view) {

      this.registerReceiver(broadCastReceiver, new IntentFilter(
            "android.intent.action.TIME_TICK"));
      Toast.makeText(this, "Registered broadcast receiver", Toast.LENGTH_SHORT)
            .show();
   }

   /**
    * This method disables the Broadcast receiver
    *
    * @param view
    */
   public void unregisterBroadcastReceiver(View view) {

      this.unregisterReceiver(broadCastReceiver);

      Toast.makeText(this, "unregistered broadcst receiver", Toast.LENGTH_SHORT)
            .show();
   }
}

1
คุณช่วยอธิบายให้ OP ทราบได้ไหมว่าทำไมนี่จึงเป็นแนวปฏิบัติที่ดีที่สุด
Martin Prikryl

1
พวกเขาไม่ได้อธิบายว่า "พวกเขา" มักจะโพสต์โค้ดเพราะคุณรู้ดีกว่ามาก -sarcasm
Neon Warge

2

ตามการฟังและการกระจายข้อความทั่วโลกและการตั้งค่าการเตือนภัยในงานทั่วไปและวิธีการทำสิ่งเหล่านั้นใน Android :

ถ้าชั้นที่ได้รับไม่ได้ลงทะเบียนใช้ในการประจักษ์ของคุณแบบไดนามิก instantiate และสามารถลงทะเบียนรับโดยการเรียกContext.registerReceiver ()

ลองดูที่registerReceiver (ตัวรับ BroadcastReceiver ตัวกรอง IntentFilter)สำหรับข้อมูลเพิ่มเติม


1
ฉันพยายามโทรออกcontext.registerReceiverแต่มันไม่ได้ถูกเรียกคุณช่วยกรุณาดูที่คำถามนี้stackoverflow.com/questions/13238600/…
ล่า

2

เป็นวิธีปฏิบัติที่ดีที่สุดที่จะต้องให้การอนุญาตเสมอเมื่อลงทะเบียนผู้รับไม่เช่นนั้นคุณจะได้รับแอปพลิเคชันใด ๆ ที่ส่งเจตนาจับคู่ วิธีนี้ช่วยให้แอปที่เป็นอันตรายสามารถแพร่สัญญาณไปยังเครื่องรับของคุณ


1

สำหรับLocalBroadcastManager

   Intent intent = new Intent("any.action.string");
   LocalBroadcastManager.getInstance(context).
                                sendBroadcast(intent);

และลงทะเบียน onResume

LocalBroadcastManager.getInstance(
                    ActivityName.this).registerReceiver(chatCountBroadcastReceiver, filter);

และยกเลิกการลงทะเบียน onStop

LocalBroadcastManager.getInstance(
                ActivityName.this).unregisterReceiver(chatCountBroadcastReceiver);

และรับมัน ..

mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("mBroadcastReceiver", "onReceive");
        }
    };

ที่ IntentFilter อยู่

 new IntentFilter("any.action.string")

1

สองทางเลือก

1) ถ้าคุณต้องการอ่านบรอดคาสต์เฉพาะเมื่อกิจกรรมปรากฏให้เห็นแล้ว

registerReceiver(...) ในonStart()และunregisterReceiver(...)ในonStop()

2) ถ้าคุณต้องการอ่าน Broadcast แม้ว่า Activity จะอยู่ในพื้นหลัง

registerReceiver(...)ทั้งในonCreate(...)และunregisterReceiver(...)ในonDestroy()

โบนัส:

หากคุณขี้เกียจ

หากคุณไม่ต้องการเขียนรหัสสำเร็จรูปเพื่อลงทะเบียนและยกเลิกการลงทะเบียน BroadcastReceiver ซ้ำแล้วซ้ำอีกในแต่ละกิจกรรม

  1. สร้างกิจกรรมที่เป็นนามธรรม
  2. เขียนรหัสสำเร็จรูปในกิจกรรม
  3. ปล่อยให้การใช้งานเป็นวิธีนามธรรม

นี่คือข้อมูลโค้ด:

กิจกรรมที่เป็นนามธรรม

public abstract class BasicActivity extends AppCompatActivity {

    private BroadcastReceiver broadcastReceiver;
    private IntentFilter filter;
    private static final String TAG = "BasicActivity";

    /**********************************************************************
    *                   Boilerplate code
    **********************************************************************/

    @Override
    public void onCreate(Bundle sis){
        super.onCreate(sis);
        broadcastReceiver = getBroadcastReceiver();
        filter = getFilter();
    }

    @Override
    public void onStart(){
        super.onStart();
        register();
    }

    @Override
    public void onStop(){
        super.onStop();
        unregister();
    }

    private void register(){
        registerReceiver(broadcastReceiver,filter);
    }

    private void unregister(){
        unregisterReceiver(broadcastReceiver);
    }

    /**********************************************************************
    *                   Abstract methods
    **********************************************************************/

    public abstract BroadcastReceiver getBroadcastReceiver();

    public abstract IntentFilter getFilter();

}

การใช้วิธีการนี้คุณสามารถเขียนรหัสสำเร็จรูปเพิ่มเติมเช่นการเขียนภาพเคลื่อนไหวทั่วไปการเชื่อมโยงกับบริการ ฯลฯ

ดูรหัสเต็ม:

ที่นี่


0

สร้างเครื่องรับสัญญาณออกอากาศ

[BroadcastReceiver (เปิดใช้งาน = จริง, ส่งออก = เท็จ)]

public class BCReceiver : BroadcastReceiver
{

    BCReceiver receiver;

    public override void OnReceive(Context context, Intent intent)
    {
        //Do something here
    }
}

จากกิจกรรมของคุณเพิ่มรหัสนี้:

LocalBroadcastManager.getInstance(ApplicationContext)
    .registerReceiver(receiver, filter);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.