Broadcast android

Tìm hiểu về Broadcast Receiver trong Android

  • Báo cáo

Bài đăng này đã không được cập nhật trong 3 năm

Broadcast Receiver là gì?

Đã bao giờ bạn tự hỏi hệ thống Android làm cách nào mà có thể nhận biết được tất cả những sự thay đổi của hê thống như lắng nghe tin nhắn đến, hành động rút – cắm sạc, hay hành động bật tắt mạng,… đó chính xác là hệ thống sử dụng Broadcast Receiver để làm. Vậy chúng ta đi vào tìm hiểu Broadcast Receiver là gì.

1. Broadcast Receiver là một trong 4 component lớn trong Android, với mục đích là lắng nghe các sự kiện, trạng thái của hệ thống phát ra thông qua Intent nhờ đó mà các lập trình viên có thể xử lí được các sự kiện hệ thống ở bên trong ứng dụng của mình.

2. Broadcast Receiver có thể hoạt động được cả khi ứng dụng bị tắt đi, nghĩa là ở background chính vì vậy nó thường được sử dụng vớiservice.

Cách đăng ký Broadcast

1. Đăng ký trong file AndroidManifest

Là cách chúng ta khai báo Broadcast Receiver trong Manifest và khi lần đầu khởi chạy ứng dụng thì nó sẽ đăng ký Broadcast và cứ thế nó start cho đến khi các bạn XOÁ ứng dụng đi.Nó vẫn lắng nghe khi các bạn đã tắt ứng dụng đi luôn nhé đây là ưu điểm của cách đăng ký này.<application android:allowBackup=”true”    android:icon=”@mipmap/ic_launcher”    android:label=”@string/app_name”    android:roundIcon=”@mipmap/ic_launcher_round”    android:supportsRtl=”true”    android:theme=”@style/AppTheme”>    <activity android:name=”.MainActivity”>        <intent-filter>            <action android:name=”android.intent.action.MAIN”/> <category android:name=”android.intent.category.LAUNCHER”/>        </intent-filter>     </activity> <receiver android:name=”.Broadcast”>         <intent-filter>             <action android:name=”android.intent.action.AIRPLANE_MODE”/>         </intent-filter>     </receiver></application>

Ở đây trong thẻ <intent-filter> có sự kiện lắng nghe là <action android:name=”android.intent.action.AIRPLANE_MODE”/> tương ứng với sự kiện bật tắt chế độ máy bay. Nếu không có action này thì chúng ta sẽ không nhận được bất kì thông báo nào khi có sự thay đổi. Ở trên chúng ta đã thực hiện đăng ký lắng nghe bây giờ chúng ta sẽ xử lý kết quả trả về bằng cách tạo một class mới extends lại BroadcastReceiverpublic class Broadcast extends BroadcastReceiver {            @Override            public void onReceive(Context context, Intent intent) {                Log.d(Broadcast.class.getSimpleName(), “Air Plane mode”);            }        }

Chúng ta Override lại hàm onReceive() và khi có sự thay đổi thì sẽ đi vào hàm này ở đây mình đặt Log để nhận biết khi có sự thay đổi bật tắt chế độ máy bay. Kết quả thu được

Broadcast android

2. Đăng ký trong file Java

Đây là cách thông dụng nhất vì đa số trong các ứng dụng chúng ta chỉ lắng nghe trong phạm vi ứng dụng của mình, khi kết thúc thì chúng ta cũng ngừng lắng nghe luôn. Chúng ta cũng làm như ở cách đăng ký ở trong file Manifest chỉ khác biệt ở trong cách đăng ký. public class MainActivity extends AppCompatActivity { private Broadcast broadcast; @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                broadcast = new Broadcast();                IntentFilter filter = new IntentFilter(“android.intent.action.AIRPLANE_MODE”);                registerReceiver(broadcast, filter);            } @Override            protected void onStop() {                super.onStop();                unregisterReceiver(broadcast);            }        }

Ở đây chúng ta tạo một cái IntentFilter để đăng ký lắng nghe hành động bật tắt chế độ máy bay, sau đó chúng ta gọi registerReceiver() truyền vào class Broadcat và cái action mà chúng ta vừa khởi tạo trước đó với mục đích là thông báo với hệ thống là ứng dụng lắng nghe sự thay đổi của cái action mà chúng ta vừa đăng ký và trả kết quả về hàm onReceive() trong class Broadcast.Có một lưu ý quan trọng là nếu sử dụng cách đăng ký bằng Java code thì nhất định phải unregister() nếu không sẽ bị lỗi kinh điển

Are you missing a call to unregisterReceiver()?

Tùy vào yêu cầu đưa ra mà chúng ta lựa chọn cách sử dụng cho phù hợp.

Custom BroadcastReceiver

Thường được sử dụng để truyền thông điệp trong và ngoài ứng dụng nhưng không phải là sự thay đổi từ hệ thống mà là những thông điệp mà lập trình viên muốn truyền đi.

Chúng ta tạo receiver nhưng ở phần action thay vì sử dụng action có sẵn của hệ thống thì chúng ta tự tạo 1 action     <application android:allowBackup=”true”            android:icon=”@mipmap/ic_launcher”            android:label=”@string/app_name”            android:roundIcon=”@mipmap/ic_launcher_round”            android:supportsRtl=”true”            android:theme=”@style/AppTheme”>            <activity android:name=”.MainActivity”>                <intent-filter>                    <action android:name=”android.intent.action.MAIN”/> <category android:name=”android.intent.category.LAUNCHER”/>                </intent-filter>            </activity> <receiver android:name=”.Broadcast”>                <intent-filter>                    <action android:name=”test.Broadcast”/>                </intent-filter>            </receiver> <activity android:name=”.TestBroadcastActivity”>            </activity>        </application>

Điểm khác biệt ở đây là mình có thêm vào đoạn code để có thể gửi được Broadcast. Mình thực hiện send Broadcast từ màn hình MainActivity vào tạo thêm một activity để nhận kết quả trả vềpublic class MainActivity extends AppCompatActivity { @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent();        intent.setAction(“test.Broadcast”);        sendBroadcast(intent);    }}

Ở Activity nhận kết quả trả về mình đăng ký nhận và hủy Broadcast và cũng sử dụng lại class Broadcast ở trên.public class TestBroadcastActivity extends AppCompatActivity { private Broadcast mBroadcast; @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test_broadcast);        mBroadcast = new Broadcast();        IntentFilter filter = new IntentFilter(“test.Broadcast”);        registerReceiver(mBroadcast, filter);    } @Override    protected void onStop() {        super.onStop();        unregisterReceiver(mBroadcast);    }}

Và kết quả trả về cùng với dòng log mình đã thêm vào trong hàm OnReceive()

08-14 20:59:40.624 1798-1798/com.example.vuminhduc.demobroadcast D/Broadcast: Da nhan Broadcast tu MainActivity

Ta thấy từ cách sendBroadcast trên chúng ta có thể áp dụng để truyền dữ liệu giữa các class với nhau. Ở đây mình sẽ làm một ví dụ gửi nhận một chuỗi String và Log ra. Mình làm tương tự như trên nhưng thêm dòng code sau để gửi dữ liệu

intent.putExtra(“string_test”, “Hello”);

Và ở bên class Broadcast – nơi mà chúng ta nhận và xử lí dữ liệu thì chúng ta sử dụng dòng code

intent.getStringExtra(“string_test”)

Như vậy chúng ta đã có thể nhận được dữ liệu từ nơi bắn Broadcast rồi. Thật tiện lợi phải không nào?

Local Broadcast Receiver

Ở đây chúng ta sang tìm hiểu về Local Broadcast và những điểm khác biệt so với các cách trước nhé.

Ưu điểm

Sự khác biệt ở đây ở trong cách mà chúng ta sendBroadcast, register và unRegister

Với sendBroadcast

LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

Với RegisterBroadcast

LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcast, filter);

Và với UnRegisterBroadcast

LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcast);

Hạn chế Broadcast với permission

Khi chúng ta sử dụng cách này thì chỉ những nơi đã được cấp quyền phù hợp với bên gửi thì mới có thể nhận được Broadcast.

Với bên gửi

Khi mà bạn gọi sendBroadcast(Intent, String)hoặcsendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) bạn có thể hạn chế quyền trong tham số bằng cách

sendBroadcast(intent, Manifest.permission.RECEIVE_SMS);

Với bên nhận

Nếu chúng ta muốn nhận được Broadcast ở trên thì chúng ta phải làm theo những cách sau:

registerReceiver(mBroadcast, filter, Manifest.permission.RECEIVE_SMS, null);

Hoặc đăng ký trong file Manifest <receiver android:name=”.Broadcast”     android:permission=”android.permission.SEND_SMS”>        <intent-filter>           <action android:name=”android.intent.action.AIRPLANE_MODE”/>        </intent-filter> </receiver>

Priority between Broadcast Receivers <receiver android:name=”.Broadcast”     android:permission=”android.permission.SEND_SMS”>        <intent-filter android:priority=”1″>            action android:name=”android.intent.action.AIRPLANE_MODE”/>        </intent-filter></receiver>

Sử dụng Package Manager để Disable các Broadcast tĩnh

Khi ta có hai class kế thừa lại BroadcastReceiver tương ứng với hai đối tượng lắng nghe Broadcast thì nếu ta muốn disable Broadcast thứ hai tương ứng với class Broadcast2.class thì ta làm như sau:private void disableBroadcast(Context context) {        ComponentName receiver = new ComponentName(context, Broadcast2.class);        PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver,                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,                PackageManager.DONT_KILL_APP);    }

Các lưu ý về bảo mật và cách xử lí

  • Bạn có thể set các quyền cho Broadcast
  • Set package mà bạn muốn gửi Broadcast đến quá setPackage(String)
  • Sử dụng Local Broadcast
  • Set các quyền bạn cho là “Nguy hiểm”
  • Bạn có thể set android:exported=false
  • Local Broadcast
  • Sử dụng goAsync() trong onReceive()
  • Sử dụng JobScheduler

Tổng kết

Trên đây chúng ta vừa tìm hiểu qua Broadcast Receiver nếu có gì chưa đúng hoặc thiếu sót các bạn có thể comment ở dưới post này. Cảm ơn các bạn đã theo dõi.

Bài viết này có sử dụng tài liệu tham khảo từ https://developer.android.com/guide/components/broadcasts  

Tìm hiểu về Broadcast Receiver trong Android

  • Báo cáo

Bài đăng này đã không được cập nhật trong 3 năm

Broadcast Receiver là gì?

Đã bao giờ bạn tự hỏi hệ thống Android làm cách nào mà có thể nhận biết được tất cả những sự thay đổi của hê thống như lắng nghe tin nhắn đến, hành động rút – cắm sạc, hay hành động bật tắt mạng,… đó chính xác là hệ thống sử dụng Broadcast Receiver để làm. Vậy chúng ta đi vào tìm hiểu Broadcast Receiver là gì.

1. Broadcast Receiver là một trong 4 component lớn trong Android, với mục đích là lắng nghe các sự kiện, trạng thái của hệ thống phát ra thông qua Intent nhờ đó mà các lập trình viên có thể xử lí được các sự kiện hệ thống ở bên trong ứng dụng của mình.

2. Broadcast Receiver có thể hoạt động được cả khi ứng dụng bị tắt đi, nghĩa là ở background chính vì vậy nó thường được sử dụng vớiservice.

Cách đăng ký Broadcast

1. Đăng ký trong file AndroidManifest

Là cách chúng ta khai báo Broadcast Receiver trong Manifest và khi lần đầu khởi chạy ứng dụng thì nó sẽ đăng ký Broadcast và cứ thế nó start cho đến khi các bạn XOÁ ứng dụng đi.Nó vẫn lắng nghe khi các bạn đã tắt ứng dụng đi luôn nhé đây là ưu điểm của cách đăng ký này.<application android:allowBackup=”true”    android:icon=”@mipmap/ic_launcher”    android:label=”@string/app_name”    android:roundIcon=”@mipmap/ic_launcher_round”    android:supportsRtl=”true”    android:theme=”@style/AppTheme”>    <activity android:name=”.MainActivity”>        <intent-filter>            <action android:name=”android.intent.action.MAIN”/> <category android:name=”android.intent.category.LAUNCHER”/>        </intent-filter>     </activity> <receiver android:name=”.Broadcast”>         <intent-filter>             <action android:name=”android.intent.action.AIRPLANE_MODE”/>         </intent-filter>     </receiver></application>

Ở đây trong thẻ <intent-filter> có sự kiện lắng nghe là <action android:name=”android.intent.action.AIRPLANE_MODE”/> tương ứng với sự kiện bật tắt chế độ máy bay. Nếu không có action này thì chúng ta sẽ không nhận được bất kì thông báo nào khi có sự thay đổi. Ở trên chúng ta đã thực hiện đăng ký lắng nghe bây giờ chúng ta sẽ xử lý kết quả trả về bằng cách tạo một class mới extends lại BroadcastReceiverpublic class Broadcast extends BroadcastReceiver {            @Override            public void onReceive(Context context, Intent intent) {                Log.d(Broadcast.class.getSimpleName(), “Air Plane mode”);            }        }

Chúng ta Override lại hàm onReceive() và khi có sự thay đổi thì sẽ đi vào hàm này ở đây mình đặt Log để nhận biết khi có sự thay đổi bật tắt chế độ máy bay. Kết quả thu được

Broadcast android

2. Đăng ký trong file Java

Đây là cách thông dụng nhất vì đa số trong các ứng dụng chúng ta chỉ lắng nghe trong phạm vi ứng dụng của mình, khi kết thúc thì chúng ta cũng ngừng lắng nghe luôn. Chúng ta cũng làm như ở cách đăng ký ở trong file Manifest chỉ khác biệt ở trong cách đăng ký. public class MainActivity extends AppCompatActivity { private Broadcast broadcast; @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                broadcast = new Broadcast();                IntentFilter filter = new IntentFilter(“android.intent.action.AIRPLANE_MODE”);                registerReceiver(broadcast, filter);            } @Override            protected void onStop() {                super.onStop();                unregisterReceiver(broadcast);            }        }

Ở đây chúng ta tạo một cái IntentFilter để đăng ký lắng nghe hành động bật tắt chế độ máy bay, sau đó chúng ta gọi registerReceiver() truyền vào class Broadcat và cái action mà chúng ta vừa khởi tạo trước đó với mục đích là thông báo với hệ thống là ứng dụng lắng nghe sự thay đổi của cái action mà chúng ta vừa đăng ký và trả kết quả về hàm onReceive() trong class Broadcast.Có một lưu ý quan trọng là nếu sử dụng cách đăng ký bằng Java code thì nhất định phải unregister() nếu không sẽ bị lỗi kinh điển

Are you missing a call to unregisterReceiver()?

Tùy vào yêu cầu đưa ra mà chúng ta lựa chọn cách sử dụng cho phù hợp.

Custom BroadcastReceiver

Thường được sử dụng để truyền thông điệp trong và ngoài ứng dụng nhưng không phải là sự thay đổi từ hệ thống mà là những thông điệp mà lập trình viên muốn truyền đi.

Chúng ta tạo receiver nhưng ở phần action thay vì sử dụng action có sẵn của hệ thống thì chúng ta tự tạo 1 action     <application android:allowBackup=”true”            android:icon=”@mipmap/ic_launcher”            android:label=”@string/app_name”            android:roundIcon=”@mipmap/ic_launcher_round”            android:supportsRtl=”true”            android:theme=”@style/AppTheme”>            <activity android:name=”.MainActivity”>                <intent-filter>                    <action android:name=”android.intent.action.MAIN”/> <category android:name=”android.intent.category.LAUNCHER”/>                </intent-filter>            </activity> <receiver android:name=”.Broadcast”>                <intent-filter>                    <action android:name=”test.Broadcast”/>                </intent-filter>            </receiver> <activity android:name=”.TestBroadcastActivity”>            </activity>        </application>

Điểm khác biệt ở đây là mình có thêm vào đoạn code để có thể gửi được Broadcast. Mình thực hiện send Broadcast từ màn hình MainActivity vào tạo thêm một activity để nhận kết quả trả vềpublic class MainActivity extends AppCompatActivity { @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent();        intent.setAction(“test.Broadcast”);        sendBroadcast(intent);    }}

Ở Activity nhận kết quả trả về mình đăng ký nhận và hủy Broadcast và cũng sử dụng lại class Broadcast ở trên.public class TestBroadcastActivity extends AppCompatActivity { private Broadcast mBroadcast; @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test_broadcast);        mBroadcast = new Broadcast();        IntentFilter filter = new IntentFilter(“test.Broadcast”);        registerReceiver(mBroadcast, filter);    } @Override    protected void onStop() {        super.onStop();        unregisterReceiver(mBroadcast);    }}

Và kết quả trả về cùng với dòng log mình đã thêm vào trong hàm OnReceive()

08-14 20:59:40.624 1798-1798/com.example.vuminhduc.demobroadcast D/Broadcast: Da nhan Broadcast tu MainActivity

Ta thấy từ cách sendBroadcast trên chúng ta có thể áp dụng để truyền dữ liệu giữa các class với nhau. Ở đây mình sẽ làm một ví dụ gửi nhận một chuỗi String và Log ra. Mình làm tương tự như trên nhưng thêm dòng code sau để gửi dữ liệu

intent.putExtra(“string_test”, “Hello”);

Và ở bên class Broadcast – nơi mà chúng ta nhận và xử lí dữ liệu thì chúng ta sử dụng dòng code

intent.getStringExtra(“string_test”)

Như vậy chúng ta đã có thể nhận được dữ liệu từ nơi bắn Broadcast rồi. Thật tiện lợi phải không nào?

Local Broadcast Receiver

Ở đây chúng ta sang tìm hiểu về Local Broadcast và những điểm khác biệt so với các cách trước nhé.

Ưu điểm

Sự khác biệt ở đây ở trong cách mà chúng ta sendBroadcast, register và unRegister

Với sendBroadcast

LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

Với RegisterBroadcast

LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcast, filter);

Và với UnRegisterBroadcast

LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcast);

Hạn chế Broadcast với permission

Khi chúng ta sử dụng cách này thì chỉ những nơi đã được cấp quyền phù hợp với bên gửi thì mới có thể nhận được Broadcast.

Với bên gửi

Khi mà bạn gọi sendBroadcast(Intent, String)hoặcsendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) bạn có thể hạn chế quyền trong tham số bằng cách

sendBroadcast(intent, Manifest.permission.RECEIVE_SMS);

Với bên nhận

Nếu chúng ta muốn nhận được Broadcast ở trên thì chúng ta phải làm theo những cách sau:

registerReceiver(mBroadcast, filter, Manifest.permission.RECEIVE_SMS, null);

Hoặc đăng ký trong file Manifest <receiver android:name=”.Broadcast”     android:permission=”android.permission.SEND_SMS”>        <intent-filter>           <action android:name=”android.intent.action.AIRPLANE_MODE”/>        </intent-filter> </receiver>

Priority between Broadcast Receivers <receiver android:name=”.Broadcast”     android:permission=”android.permission.SEND_SMS”>        <intent-filter android:priority=”1″>            action android:name=”android.intent.action.AIRPLANE_MODE”/>        </intent-filter></receiver>

Sử dụng Package Manager để Disable các Broadcast tĩnh

Khi ta có hai class kế thừa lại BroadcastReceiver tương ứng với hai đối tượng lắng nghe Broadcast thì nếu ta muốn disable Broadcast thứ hai tương ứng với class Broadcast2.class thì ta làm như sau:private void disableBroadcast(Context context) {        ComponentName receiver = new ComponentName(context, Broadcast2.class);        PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver,                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,                PackageManager.DONT_KILL_APP);    }

Các lưu ý về bảo mật và cách xử lí

  • Bạn có thể set các quyền cho Broadcast
  • Set package mà bạn muốn gửi Broadcast đến quá setPackage(String)
  • Sử dụng Local Broadcast
  • Set các quyền bạn cho là “Nguy hiểm”
  • Bạn có thể set android:exported=false
  • Local Broadcast
  • Sử dụng goAsync() trong onReceive()
  • Sử dụng JobScheduler

Tổng kết

Trên đây chúng ta vừa tìm hiểu qua Broadcast Receiver nếu có gì chưa đúng hoặc thiếu sót các bạn có thể comment ở dưới post này. Cảm ơn các bạn đã theo dõi.

Bài viết này có sử dụng tài liệu tham khảo từ https://developer.android.com/guide/components/broadcasts