问题
In AndroidManifest.xml
I have a BroadcastReceiver
:
<receiver android:name=".SmsMonitor">
<intent-filter android:priority="-100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
In my MainActivity
, I have RecyclerView
with a list of received SMS.
My question is - How I can update the RecyclerView
from my BroadcastReceiver
"SmsMonitor" in case new SMS received when the application is running?
UPD: I mean I need solution for both states - for running application AND for state when application is not running, in one receiver. Because I have to take SMS all time while phone is working. And in case the application is running I want to update RecyclerView
.
回答1:
You need to have the BrodcastReceiver
in your MainActivity
or Fragment
as well which hosts the RecyclerView
. So that when the new SMS is received, you can call the notifyDataSetChanged
on the adapter of your RecyclerView
to update it.
Declare a BroadcastReceiver
in your Activity
like the following. This can be an inner class of your MainActivity
class.
class SMSBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// Update your RecyclerView here
// by calling notifyDataSetChanged on the adapter
}
}
}
}
Now create an instance of this BroadcastReceiver
in the onCreate
function of your MainActivity
and register the receiver.
You need to ask for SMS permission first in your Activity
like the following.
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.RECEIVE_SMS}, 0);
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
}
Do not forget to un-register the receiver in the onDestroy
function of your MainActivity
.
Hope that helps!
Update
Based on the comment below this answer, you have two cases.
Case 1. The app is running.
Case 2. The app is not running.
For case 1: The local BroadcastReceiver
like I shown above, is good enough to update the RecyclerView
instantly when a new SMS arrives. As you are handling the BroadcastReceiver
from the MainActivity
this should not be a problem, as you have the reference to your RecyclerView
.
Now for Case 2: If you are able to detect any new SMS arrival, you can save the new SMS received in your local database. You need to have an SQLite database for your application which will store all the SMS and the RecyclerView
in your application should populate the data from the database table where the SMS are stored. I hope you get the idea - just store the SMS in your local database associated with your application and when you run the application and launch the MainActivity
, read the SMS from your local database and show them in your RecyclerView
.
回答2:
I tried to do it through the Service
, but I did not succeed.
But I found simple solution:
I still have BroadcastReceiver
SmsMonitor
, registered in AndroidManifest.xml
And in the point where I create instance of my RecyclerAdapter
:
mainAdapter = new MainAdapter(this);
After this I register another BroadcastReceviver
:
BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setInitialData();
mainAdapter.notifyDataSetChanged();
}
};
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.registerReceiver(br, filter);
And in setInitialData()
I recreate all list of data for RecyclerView
.
And now I have two independently working BroadcastReceiver
. The first working the BroadcastReceiver
from the AndroidManifest.xml
, and then working the BroadcastReceiver
registered in MainActivity.
来源:https://stackoverflow.com/questions/54736055/how-to-update-recyclerview-from-broadcastreceiver