I'm making a chat app and using intent service for sending messages to firebase database even after activity is destroyed. When the uploading is successful i want to clear text in Edittext in the IntentService class but don't know how to do it.
Acivity class code
Intent sendmsgService = new Intent(getApplicationContext(),SendMessageService.class);
sendmsgService.putExtra("msg",message);
sendmsgService.putExtra("time",time);
sendmsgService.putExtra("cuser",current_user);
sendmsgService.putExtra("otheruser",otherusername);
startService(sendmsgService);
IntentService class code
public class SendMessageService extends IntentService {
DatabaseReference msgDatabase , mDatabase;
String current_user,otherusername,message,time;
public SendMessageService() {
super("SendMessageService");
mDatabase = FirebaseDatabase.getInstance().getReference();
msgDatabase = mDatabase.child("messages").child(current_user).child(otherusername);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
assert intent!=null;
message = intent.getStringExtra("msg");
time = intent.getStringExtra("time");
current_user = intent.getStringExtra("cuser");
otherusername = intent.getStringExtra("otheruser");
DatabaseReference push_database = msgDatabase.push();
String msg_push = push_database.getKey();
DatabaseReference d = FirebaseDatabase.getInstance().getReference();
String cuser = current_user+"/"+otherusername+"/";
String ouser = otherusername+"/"+current_user+"/";
Map<String,Object> chatitems = new HashMap<>();
chatitems.put("seen",false);
chatitems.put("msg",message);
chatitems.put("from",current_user);
Map<String,Object> msgitemmap = new HashMap<>();
chatitems.put("time", ServerValue.TIMESTAMP);
msgitemmap.put("servertime",ServerValue.TIMESTAMP);
msgitemmap.put("time",time);
msgitemmap.put("msg",message);
msgitemmap.put("from",current_user);
msgitemmap.put("to",otherusername);
msgitemmap.put("seen",false);
msgitemmap.put("key",msg_push);
Map<String,Object> chatmap = new HashMap<>();
chatmap.put("chatlist/"+cuser,chatitems);
chatmap.put("chatlist/"+ouser,chatitems);
chatmap.put("messages/"+cuser+msg_push,msgitemmap);
chatmap.put("messages/"+ouser+msg_push,msgitemmap);
d.updateChildren(chatmap).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
//Here i want to clear the edittext
}
});
}}
If any other solution please suggest.
Intent service runs on background thread not on main(UI) thread but we can use the Handler mechanism to send/update data to activity.
To send data to activity you need to declare handler in your activity like:
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle reply = msg.getData();
// do whatever with the bundle here
}
};
in the intent service class pass data in this way:
Bundle bundle = intent.getExtras();
if (bundle != null) {
Messenger messenger = (Messenger) bundle.get("messenger");
Message msg = Message.obtain();
msg.setData(data); //put the data here
try {
messenger.send(msg);
} catch (RemoteException e) {
Log.i("error", "error");
}
}
Most Important invoke the intent service from activity to pass handler to it:
Intent intent = new Intent(this, IntentService1.class);
intent.putExtra("messenger", new Messenger(handler));
startService(intent);
Hope this will help you
Simple solution is to use Broadcast Reciever Declare this in your activity class
BroadcastReceiver broadCastNewMessage = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do your stuff here
edittext.setText("");
}
};
Now in onCreate() register this
registerReceiver(this.broadCastNewMessage, new IntentFilter("uploading_done"));
And in onDestroy()
unregisterReceiver(broadCastNewMessage);
Now Call this method from the service class where u want to update the activity
sendBroadcast(new Intent().setAction("uploading_done"));
Related
In the Android application I'm working on, I have one activity where the user inputs data that is saved using SharedPreferences, and is used for certain calculations on the main activity. An issue I'm having is that after saving the data, the changes do not actually take effect until after the application is restarted. Is there a way I can make it so the variables associated with these SharedPreferences are updated before restarting?
Here is where I save the data in a separate activity.
saveBn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
weightString = weightText.getText().toString();
ageString = ageText.getText().toString();
getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit()
.putString("savedWeight", weightString).commit();
getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit()
.putString("savedAge", ageString).commit();
//Intent i = new Intent("com.williammiller.capstonelapv2.MainActivity");
//startActivity(i);
finish();
}
});
And here is where I'm checking in the main activity to see what they are
String age = getSharedPreferences("PREFERENCE", MODE_PRIVATE)
.getString("savedAge", "25");
String weight = getSharedPreferences("PREFERENCE", MODE_PRIVATE)
.getString("savedWeight", "200");
startBn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "weight = " + weightInt + " age = " + ageInt, Toast.LENGTH_LONG).show();
}
});
You can use a BroadcastReceiver to achieve that. Do as following:
Register a BroadcastReceiver in your Main Activity:
public static final String UPDATE_ACTION = "yourpackage.update";
public static final String EXTRA_KEY_AGE = "key_age";
public static final String EXTRA_KEY_WEIGHT = "key_weight";
private BroadcastReceiver mReceiver;
// In the onCreate() method
mReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(UPDATE_ACTION)){
// Here you get the update data from another activity
String age = intent.getStringExtra(EXTRA_KEY_AGE);
String weight = intent.getStringExtra(EXTRA_KEY_WEIGHT);
}
}
};
registerReceiver(receiver, new IntentFilter(UPDATE_ACTION ));
// Add the following code to onDestroy() method
unregisterReceiver(mReceiver);
Send a broadcast in your "separate activity":
public void onClick(View v) {
weightString = weightText.getText().toString();
ageString = ageText.getText().toString();
Intent intent = new Intent(MainActivity.UPDATE_ACTION );
intent.putExtra(MainActivity.EXTRA_KEY_AGE, ageString);
intent.putExtra(MainActivity.EXTRA_KEY_WEIGHT, weightString );
sendBroadcast(intent);
}
Update: Change part of the code to unregister the BroadcastReceiver when activity is destroyed.
I want to start an activity through IntentService, but the catch is the activty name or the class name will be passed as parameter to the IntentService.
Following are my code blocks...
public class Runner {
Context context;
public void startActivity() {
Intent intent = new Intent(context, ActivityLauncher.class);
intent.putExtra("caller", "Runner");
//CameraActivity is my activity which i want to start
// I will be giving other activities also in other parts of my code
intent.putExtra("class",CameraActivity.class);
context.startService(intent);
}
}
Now the code for ActivityLauncher Service is as follows.....
public class ActivityLauncher extends IntentService {
public ActivityLauncher(String name) {
super("ActivityLauncher");
}
protected void onHandleIntent(Intent intent) {
try{
Bundle b = intent.getExtras();
Class<?> c = (Class<?>) b.get("class");
Intent mainActivityIntent = new Intent(getBaseContext(), c.getClass());
mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String intentType = intent.getExtras().getString("caller");
if(intentType == null)
return;
if(intentType.equals("Runner"))
getApplication().startActivity(mainActivityIntent);
} catch (Exception localException) {
Log.d("TAG", localException.getMessage());
}
}
}
Please tell me how can i improve my code. and how can i get the solution.
MainActivity.java
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anaekran);
Thread t = new Thread(new Runnable() {
public void run() {
String smsMsj = getIntent().getStringExtra("sms");
if(smsMsj != null){
Toast.makeText(getApplication(), smsMsj, 2).show();
}
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle mesaj = intent.getExtras();
SmsMessage[] smsMessage = null;
String msj = "";
if(mesaj!= null){
Object[] pdus = (Object[])mesaj.get("pdus");
smsMessage = new SmsMessage[pdus.length];
for(int i = 0; i < pdus.length; i++){
smsMessage[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
msj = smsMessage[i].getMessageBody();
}
Intent mIntent = new Intent(context, SmsReceiver.class);
mIntent.putExtra("sms", msj);
}
}
}
My receiver working correctly but i have one problem when message coming i want to show on my MainAcitivty toast, so i create mIntent in receiver class, and then im use putExtra method.
But not working, sory for my bad english and thank you :)
Perhaps using explicit Intent and starting it could help you, hm? :)
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.putExtra("sms", msj);
context.startActivity(mIntent);
Your mistake is that you construct your new Intent with SmsReceiver.class (but you need to launch MainActivity) and that you do not start any activity with such an intent.
Edit 1: Also, pay attention - you are trying to run a toast inside your worker thread. This is not possible. Remove your anonymous Thread and move your toast code to your onCreate(Bundle):
protected void onCreate(Bundle saveState){
....
String smsMsj = getIntent().getStringExtra("sms");
if(smsMsj != null){
Toast.makeText(getApplication(), smsMsj, 2).show();
}
....
}
Edit 2: Moreover, your duration parameter in Toast.makeText(..) is set to 2. This does not correspond to any magic constant in Toast class. You have to use one of the constants: Toast.LENGTH_LONG or Toast.LENGTH_SHORT. So, rewrite your code to:
Toast.makeText(getApplication(), smsMsj, Toast.LENGTH_SHORT);
In my android application I have a MainActivity. It has an EditText and a Button. User enter his twitter handle and press button. An IntentService is launched which retrieves user's tweets and then return the first tweet to a BroadcastReceiver.
Since loading tweets takes time I want to show a loader until loading tweets is done.
I'm using following code in button click listener to show the loading dialog
ProgressDialog progress = new ProgressDialog(MainActivity.this);
progress.setTitle("Loading");
progress.setMessage("Wait while loading...");
progress.show();
But I don't know how to hide this once the loading is done.
Below are the code of the MainActivity , IntentService and BroadcastReceiver
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
analyze = (Button)findViewById(R.id.analyze);
twitter_username = (EditText)findViewById(R.id.twitter_username);
analyze.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
ProgressDialog progress = new ProgressDialog(MainActivity.this);
progress.setTitle("Loading");
progress.setMessage("Wait while loading...");
progress.show();
Intent i = new Intent(MainActivity.this , TwitterChecker.class);
i.putExtra("username", twitter_username.getText().toString());
startService(i);
}});
}
IntentService
public class TwitterChecker extends IntentService {
public TwitterChecker(){
super("TwitterChecker");
}
#Override
protected void onHandleIntent(Intent intent) {
String username = intent.getStringExtra("username");
TwitterAuthenticator authenticator = TwitterAuthenticator.getInstance();
String accessToken = null;
try {
accessToken = authenticator.authenticate();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (AuthenticationException e) {
e.printStackTrace();
}
Twitter tweets = FetchTweets.fetch(accessToken , username);
Log.i("Info" , "IntentService started");
Intent tweet = new Intent("com.kaysush.action.TWEET");
tweet.putExtra("tweet", tweets.get(0).getText());
sendBroadcast(tweet); // Once loaded the tweet is sent to the Receiver
}
}
BraodcastReceiver
public class TweetsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TWEET RECEIVED" , intent.getStringExtra("tweet"));
//Once loading is done a toast is shown
Toast.makeText(context, intent.getStringExtra("tweet"), Toast.LENGTH_LONG).show();
}
}
Hide a ProgressDialog once data is loaded
You are able to do it but you need to use not static but dynamic BroadcastReceiver. So here is solution:
At first, register in your Activity BroadcastReceiver dynamically:
private void registerReceiver() {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Const.LOADING_COMPLETE_ACTION)) {
if (dlg != null) {
dlg.dismiss();
}
}
}
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Const.LOADING_COMPLETE_ACTION);
registerReceiver(receiver, intentFilter);
}
And then in your IntentService, all what you need is to send Broadcast:
sendBroadcast(new Intent(Const.LOADING_COMPLETE_ACTION));
Note: Also define your ProgressDialog variable on Activity scope to have access to it from onReceive() method.
ProgressDialog progress; // Make global
Assign onClick listener
progress = new ProgressDialog(MainActivity.this);
Then in call back method onReceive()
progress.cancel();
I am trying to start an activity after n seconds with a handler. The application was crashing on the startActivity call, so I put the handler code in my application's onCreate, and it is still crashing (which makes me think that the error comes from me not using startActivity well) :
#Override
public void onCreate(){
String roomName = this.getSettingValue(R.string.PREFERENCES_ROOM_NAME, "");
Room room;
try {
room = this.getRoomWithName(roomName);
} catch (ReservatorException ex) {
Toast err = Toast.makeText(this, ex.getMessage(),
Toast.LENGTH_LONG);
err.show();
return;
}
Intent i = new Intent(this, RoomActivity.class);
i.putExtra("room", room);
this.startActivity(i);
}
Strange thing is that this work when called from a view, by using exactly the same code, but different context :
Intent i = new Intent(getContext(), RoomActivity.class);
// ...
I am pretty new to Android ... so there may be information missing in that question, or I might even be trying to do something completely stupid who knows ?
EDIT
Link to the stacktrace : http://pastebin.com/vh2QC3xz
EDIT2
Here is the handler version of my code (so what I am trying to do in the end) :
public class ReservatorApplication extends Application {
private GoToFavouriteRoom goToFavouriteRoomRunable;
class GoToFavouriteRoom implements Runnable {
ReservatorApplication app;
public GoToFavouriteRoom(ReservatorApplication anApp){
app = anApp;
}
#Override
public void run() {
String roomName = app.getSettingValue(R.string.PREFERENCES_ROOM_NAME, "");
Room room;
try {
room = app.getDataProxy().getRoomWithName(roomName);
} catch (ReservatorException ex) {
Toast err = Toast.makeText(app, ex.getMessage(),
Toast.LENGTH_LONG);
err.show();
return;
}
RoomActivity.startWith(app, room);
}
}
private final ReservatorAppHandler handler = new ReservatorAppHandler();
class ReservatorAppHandler extends Handler{
#Override
public void handleMessage(Message msg){
return;
}
}
#Override
public void onCreate(){
String serverAddress = getSettingValue(R.string.PREFERENCES_SERVER_ADDRESS, "mail.futurice.com");// TODO: change to mail.futurice.com before delivery
proxy = new SoapDataProxy(serverAddress);
// proxy = new DummyDataProxy();
proxy = new CachedDataProxy(proxy);
addressBook = new FumAddressBook();
try {
addressBook.prefetchEntries();
} catch (ReservatorException e) {
// TODO: DIE!
}
goToFavouriteRoomRunable = new GoToFavouriteRoom(this);
handler.postDelayed(goToFavouriteRoomRunable, 20000);
}
Ok ... I finally solved my problem, mainly thanks to #Drax
Apparently, you just can't start an activity from an application ... you need an instance of an activity. So :
public class ReservatorApplication extends Application {
#Override
public void onCreate(){
Intent i = new Intent(this, RoomActivity.class);
this.startActivity(i);
}
}
Is just not valid, and causes a RunTimeException ...
As far as crashing is concern when you start activity in handler with "this". it will take handler's context. and when you do getContext() it will take activity context.
Intent i = new Intent(YourActivityName.this, RoomActivity.class);
or
Intent i = new Intent(getBaseContext(), RoomActivity.class);
It`s hard to answer without seeing the stack trace from logcat, but I found that sometimes you need to pass the application context to the a new Intent before starting an Activity.
Try this line:
Intent i = new Intent(getApplicationContext(), RoomActivity.class);