Refresh listview adapter on GSM notification receive - java

Say listview.java is a file that creates adapter and assigns it to a listview.
What I want is when I receive a GSM notification I want to refresh that listview adapter. So as soon as I receive notification my listview should contain new data.
I am using onMessageReceived(String from, Bundle data) this method of GcmListenerService.
Can I call some method of listview.java from class MyGcmListenerService extends GcmListenerService {} that will refresh the adapter and assign to listview?
If user is already on listview layout then I want it to get updated with new data.
Any Idea folks how to do it?
More clarity
in listview.java I create an adapter using data from shared prefs.
when I receive GSM notification I do some changes to shared prefs. Now I want My adapter should be recreated from with new shared prefs and should be assigned to list view.
Now folks?

Inside the onMessageReceived(String from, Bundle data) you can try doing listviewAdapter.notifyDataSetChanged(). From the docs of notifyDataSetChanged
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

You can use broadcast receiver in service on method onRecieve like this
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
And in activity you will will have to implement changes like this
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-event-name".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
//here refresh your listview
// adater.notifyDatasetChanged();
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
and on receive method refresh your adapter using adater.notifydatasetchanged

Use BroadcatReceiver for refresh listview while receiving Push Notification.
In your activity of ListView add below code,
ListView Activity
#Override
public void onCreate(Bundle savedInstanceState) {
-------
IntentFilter filter = new IntentFilter(1001);
LocalBroadcastManager.getInstance(this).registerReceiver(
handlePushNewMessage, filter);
}
private final BroadcastReceiver handlePushNewMessage = new BroadcastReceiver() {
#Override
public void onReceive(Context context, final Intent intent) {
// Update list here and refresh listview using adapter.notifyDataSetChanged();
}
};
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(handlePushNewMessage);
super.onDestroy();
}
In MyGcmListenerService.java add below code on onMessageReceived()
Intent intent1 = new Intent(1001).putExtra("MESSAGE", message);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

Related

Pass int to another Activity

Before you flame me:
I know there are uncountable tutorials out there, and I know myself how to pass data to another ACtivity, just like that.
In my case that's diffrent tho. "Usually" data is passed to another activity through Intents, Bundles ecc and the other Activity is started.
Here's my case:
I have an Item with 4 parameters (Image, String,String, int)
In an AdapterClass I have a PopUpView which retakes those 4 parameters.
What I'd like to achieve is the following:
With the click of a button, the 4th parameter, the int should be sent to the Main activity and inserted in a textView inside the MainActivity, without (here's the main diffrence between this and the other questions)launching the Main Activity.
How can this be done?
TIA.
use BroadcastReceiver to send that 4th int to MainActivity
in PopupView do these:
Intent intent = new Intent("SOMEACTION");
intent.putExtra("4th_int", value);
activity.sendBroadcast(intent);'
//In MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter("SOMEACTION");
this.registerReceiver(mReceiver , filter);
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(this.mReceiver );
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == "SOMEACTION") {
// retrieve the 4th int value and update something in MainActivity
}
}
};

Add list item in RecyclerView Adapter on receiving Firebase message

I'm using the firebase messaging service for messaging and notifications. I can't seem to be able to pass an incoming message from the service to the adapter so that when the message is received it can be inserted into the RecycleView List.
I tried using BroacastIntent as follows :
public class messaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage m) {
store(m.getData());
broadcastIntent();
}
public void broadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.myApp.CUSTOM_EVENT");
sendBroadcast(intent);
}
}
and in the Adpter
public class ConvoAdapter extends RecyclerView.Adapter<ConvoHolder> {
private List<Message> list;
private Activity A;
public ConvoAdapter(List<Message> data) {
}
#Override
public ConvoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ConvoHolder(v);
}
#Override
public void onBindViewHolder(ConvoHolder h, int Position) {
final Message M = list.get(Position);
h.config(A, M);
}
#Override
public int getItemCount() {
return list.size();
}
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
}
}
}
And manifest.
<receiver android:name=".fragments.chats.ConvoAdapter$MyReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.CUSTOM_EVENT">
</action>
</intent-filter>
</receiver>
As is, the broadcast receiver is not receiving any messages.
I'd also use any other method that doesn't involve using broadcast receivers.
The flow or architecture of your is not a standard practice.
The standard flow should be
Firebase service
Some activity or fragment with BroadcastReceiver using LocalBroadcastManager
1. Firebase Service
public class messaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage m) {
store(m.getData());
broadcastIntent();
}
public void broadcastIntent() {
Intent intent = new Intent();
intent.setAction("com.myApp.CUSTOM_EVENT");
// We should use LocalBroadcastManager when we want INTRA app
// communication
LocalBroadcastManager.getInstance(YOUR_CONTEXT).sendBroadcast(intent);
}
}
2. Activity
Registering Receiver for broadcast from Service
public void onCreate(Bundle savedInstance) {
// REST OF YOUR CODE
IntentFilter if= new IntentFilter("com.myApp.CUSTOM_EVENT");
LocalBroadcastManager.getInstance(this).registerReceiver(onMessage, if);
}
Writing the Receiver in Activity
private BroadcastReceiver onNotice= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Update your RecyclerView here using notifyItemInserted(position);
}};
Summary: The Service sends local broadcast to Activity which in turn receives it and updates or add items using RecyclerView instance
if in case you don't want to use BroadCaseReceiver for your task.Follow below steps:
There are two things to note here.
Firstly,Check whether the Activity is open(Activel visible) or not.
i. When your screen is active.(screen is visible).
1.In your onMessageReceived() store the received message in SQLiteDataBase with time.
2.create a method in your adapter which will update the screen by fetching the data from SQLiteDB.
3.Now whenever a new message is received call this method in Adapter class.
ii.in case the screen is not active:
1.store the received message in sqliteDb and show it as a notification.
note:
1.make sure you write all these in a try catch block.
2.make sure to sync your SQLiteDB on opening the screen for the first time.
3.in case if this does not help you please try this way.. Refreshing activity on receiving gcm push notification
I think the above code didnt worked because the action name above given and the one registered in manifest is different
<action android:name="com.myApp.CUSTOM_EVENT">
</action>
intent.setAction("com.myApp.CUSTOM_EVENT");
give same name i think the above code will work

Android - LocalBroadcast

I searched a lot but didn't find the solution to the following issue.
Context :
I use an AsyncHttpResponseHandler object to handle all my webservice
responses
If I get a particular error code from the WS, I want to show an alert dialog (whatever the activity currently displayed)
I came to think that using the LocalBroadcastManager would be a good solution as the HTTP handler is not aware of the currently displayed activity
Problem :
After implementation of all what seems to be needed to make it work, my intent sent from the async handler is not received.
Additional note :
the ApplicationContext is stored in my StaticItems
class which contains all the static data I need in my app.It is setup via a custom class which inherits from Application
If I broadcast the intent from an activity, the OnReceive event is triggered
I thank you in advance for any help you could provide.
Cheers !
Here are some pieces of my code :
The code in the http handler
public class AsyncResponseHandler extends AsyncHttpResponseHandler {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
if(response != null && response.length > 0) {
CrvData data = JsonHelper.getCrvData(new String(response));
String code = data.getErrorCode();
if (!TextUtils.isEmpty(code) && code.equals(StaticItems.C_WS_OBSOLETE_VERSION_ERROR)) {
Intent intent = new Intent();
intent.setAction(StaticItems.BROADCAST_INTENT_MESSAGE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse(data.getValue()));
LocalBroadcastManager.getInstance(StaticItems.applicationContext).sendBroadcast(intent);
}
}
}
The code of the root Activity I use for all my activities :
public class MainActivity extends Activity {
/**
* The local broadcast receiver
*/
protected MyBroadcastReceiver mMessageReceiver = new MyBroadcastReceiver();
#Override
protected void onResume() {
super.onResume();
// register
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_DEFAULT);
filter.addAction(StaticItems.BROADCAST_INTENT_MESSAGE);
LocalBroadcastManager.getInstance(StaticItems.applicationContext).registerReceiver(mMessageReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
// Unregister
LocalBroadcastManager.getInstance(StaticItems.applicationContext).unregisterReceiver(mMessageReceiver);
}
}
The receiver
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setInverseBackgroundForced(true)
.setNegativeButton(context.getResources().getString(R.string.dlg_no), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setIcon(R.drawable.ic_dialog_alert_holo_light)
.setMessage(R.string.dlg_app_is_obsolete)
.setPositiveButton(context.getResources().getString(R.string.dlg_yes), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
context.startActivity(intent);
}
});
builder.show();
}
}
I had a similar problem, for some reason you can not setData(..) on Intent returned via LocalBroadcastManager, when I placed my URI in the extra data, it started to work.... possibly a bug?
My guess is that the context you are using is not an activity context and thus can't be used for creating dialogs.
Namely, the context that is passed to onReceive in this case should be your application context, StaticItems.applicationContext, which is not good for showing dialogs.
If this is the case, you should somehow rearrange your code to make sure to pass an activity context rather than the application one.
Remove addCategory() from your IntentFilter
was solved here
OK so... I figured out that the intent was not received because of this line :
intent.setData(Uri.parse(data.getValue()));
And as #mvai pointed, the dialog cannot be displayed from the application context. I managed to get the current activity by having a reference to it in my application class. (I checked out to be sure for not having any memory leak)

refresh activity from service after notification

I have a service
public class GcmIntentService extends IntentService{...}
that manages the notifications.
When a notification arrives if the user is out of the application, with a tap on the notification the main activity is resumed and updated
public class MainActivity extends Activity {
...
lv = (ListView) findViewById(R.id.lv);
adapter = new Adapter(this, item);
lv .setAdapter(adapter);
...
}
but how can I update the activity if the user is already on it?
You have to use BroadcastReciever for this task:http://developer.android.com/reference/android/content/BroadcastReceiver.html
in Activity:
public class MainActivity extends Activity {
public static final String NOTIFY_ACTIVITY_ACTION = "notify_activity";
private BroadcastReciver broadcastReciver;
#Override
protected void onStart() {
super.onStart();
broadcastReciver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction.equals(NOTIFY_ACTIVITY_ACTION ))
{
//to do smth
}
}
}
IntentFilter filter = new IntentFilter( NOTIFY_ACTIVITY_ACTION );
registerReceiver(broadcastReciver, filter);
}
#Override
protected void onStop()
{
unregisterReceiver(broadcastReciver);
}
}
In Service:
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(MainActivity.NOTIFY_ACTIVITY_ACTION );
broadcastIntent.putExtra("addtional_param", 1);
broadcastIntent.putExtra("addtional_param2", 2); //etc
sendBroadcast(broadcastIntent);
UPDATE
BTW It's better use LocalBroadcastManager for send broadcast inside the app. It uses the same way as normal broadcast, but first you create LocalBroadcastManager:
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(MainActivity.this);
and in the onStart:
manager.registerReciever(broadcastReciver, filter);
and in the onStop:
manager.unregisterBroadcast(broadcastReciver);
and in the service:
manager.sendBroadcast(broadcastIntent);
if you are using the list and you would like to reload the activity just to refresh the list then, I would suggest you to use following methods on your adatper as soon as some message arrives. This would refresh the content in the list, and list will be updated automatically (without restarting of activity)
adapter.notifyDataSetChanged()
This method notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
It's not a good option to reload the activity, but if there is no other solution rather than recreating the activity i would suggest to refresh the view itself.
Hope this helps.

NullPointerExceptoin when passing value from activity to broadcast receiver

I have an easy question.
I have declared text view in main activity, and created it from XML (findViewById). I would like to pass this value to a subclass of broadcast receiver. Following is my Broadcast constructor:
public Broadcast(TextView text_dBm) {
this.text_dBm = text_dBm;
}
In my main activity I create a new broadcast object and pass my textview value inside, like this:
new Broadcast(text_dBm);
But I'm still getting null pointer exception on my text_dBm. Is there anyway (besides static methods) to pass values between activites and broadcast receiver?
Oh and yes. My broadcast receiver is registered programmatically (in service), and its running perfectly.
Thank you for your time!
P.S: I already checked some threads here in SO, but i didn't find an answer:
How to pass value from an activity in an broadcast receiver?
Main activity class:
public class MainActivity extends Activity {
TextView text_dBm, text_time, text_rssi;
Intent startServiceFromActivity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text_dBm = (TextView) findViewById(R.id.textView_dBm);
new Broadcast(text_dBm);
startServiceFromActivity = new Intent(this, WifiService.class);
startService(startServiceFromActivity);
}
}
Broadcast receiver class:
public class Broadcast extends BroadcastReceiver {
WifiInfo wifiInfo;
WifiManager wifiManager_service;
TextView text_dBm;
public Broadcast(WifiManager wifiManager_service) {
this.wifiManager_service = wifiManager_service;
}
public Broadcast(TextView text_dBm) {
this.text_dBm = text_dBm;
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("RECEIVER", "Receiver running"); // LOG
text_dBm.setText("textview"); // nullpointerexception
}
}
You can't pass around views using Intents. To do what you want to do, you will need your broadcast receiver to be an inner class of your activity. The receiver should be registered when activity is started and unregistered when activity is stopped. Else you will leak memory. That means that you will only be able to receive your messages when actually on the activity screen itself.
If you need to be able to receive broadcasts outside the activity, you will need to:
register your receiver in the manifest for a given action (or in a service, but don't forget to unregister it)
start the activity and pass the message to show in the textview using an intent extra
when the activity starts, check if the intent contains anything to show in the textview and do the necessary
From your comment:
Create the receiver as an inner class of the activity (not a static one so it can access the activity's TextView instance)
register the receiver in onStart
unregister the receiver in onStop
In the onReceive method of your receiver do: textView.setText(intent.getStringExtra("dbm"));
Service sends the broadcast by passing an intent extra called "dbm" and containing the text you want to display
-
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbmView = (TextView) findViewById(R.id.textView_dBm);
}
#Override
protected void onStart() {
super.onStart();
IntentFilter intentFilter = new IntentFilter("com.example.broadcasts.DBM_UPDATE");
registerReceiver(receiver, intentFilter);
}
#Override
protected void onStop() {
unregisterReceiver(receiver);
super.onStop();
}
private TextView dbmView;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
dbmView.setText(intent.getStringExtra("dbm"));
}
}
}
In the service:
Intent i = new Intent("com.example.broadcasts.DBM_UPDATE");
i.putExtra("dbm", "it works!");
sendBroadcast(i);
Pass data Through intent
Activity -
Intent i = new Intent(Activity.this, Broadcast.class);
Bundle b = new Bundle();
b.putString("key", "value");
i.putExtras(b);
startActivity(i);
In your broadcast receiver class onReceive method
#Override
public void onReceive(Context context, Intent intent)
{
String result = intent.getString("key");
// your method
}

Categories