I have an activity A which has a progressbar and a textview.
If user clicks a button a service is being started (ServiceB), I am trying to find a way how to update the progressbar in Activity A from the ServiceB and at the same time set the (progress) text in the Textview in Activity A.
I looked around on Google and Stackoverflow and I think I found a way to do it as described here
but I am having difficulties to implement this, any help is highly appreciated.
PS: don`t downvote, I know UI should not be directly accessed from a Service, so I am looking for a way to do it right.
Some relevant code:
Activity A:
#EActivity(R.layout.downloads_activity)
public class DownloadsActivity extends BaseActivity {
#ViewById(R.id.progress_text)
TextView progresstxt;
#ViewById(R.id.progressdownload)
ProgressBar downloadprogress;
// Update Progressbar and set Text sent from ServiceB
}
ServiceB:
public class ServiceB extends IntentService {
...
#Override
public void onProgress(DownloadRequest request, long totalBytes, long downloadedBytes, int progress) {
int id = request.getDownloadId();
if (!isActive) {
downloadManager.cancel(downloadId1);
deleteCancelledFile.deleteOnExit();
} else if (id == downloadId1) {
// How to update progressbar and textview of Activity A?
progresstxt.setText("Downloading: " + progress + "%" + " " + getBytesDownloaded(progress, totalBytes));
downloadprogress.setProgress(progress);
}
}
...
}
You need to use LocalBroadcastManager
Following are the steps which needs to be taken care
Create a LocalBroadcastManager inside activity.
private BroadcastReceiver mLocalBroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// take values from intent which contains in intent if you putted their
// here update the progress bar and textview
String message = intent.getStringExtra("message");
int progress = Integer.parseInt(intent.getStringExtra("progress"));
}
};
Register it on activity's onCreate()
LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcast ,
new IntentFilter("myBroadcast"));
UnRegister in activity's onDestroy()
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocalBroadcast );
Send updates from service to activity to update UI
From IntentService send progress and textView update via intent
Intent intent = new Intent("myBroadcast");
// You can also include some extra data.
intent.putExtra("message", "This is my message!"); // msg for textview if needed
intent.putExtra("progress", progressValue); // progress update
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
It will send these data to mLocalBroadcast which we register inside activity
Hope these help you.
Related
Here I have 3 activity and ActivityA contain textView which show username , ActivityB contain only button to redirect ActivityC, ActivityC Contain EditText and save button.
Now i want to change updated text from ActivityC to direct ActivityA when save button clicked without refreshing any Activity than what i have to do? can you please suggest simple way.
I have a same requirement in complex project, i need to save user location at server side using api call and show updated data in ActivityA.
Another way would be to use LocalBroadcastManager.
The code will be as follows.
//ACTIVITY A CODE
TextView username_tv;
String username;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
username_tv = (TextView) findViewById(R.id.username_tv);
//Get your username and store it in username
username = getYourUsername();
username_tv.setText(username);
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
lbm.registerReceiver(receiver, new IntentFilter("USER_NAME_CHANGED_ACTION"));
}
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
username = intent.getStringExtra("username");
username_tv.setText(username);
}
}
};
//ACTIVITY C CODE
//ADD this code to your 'SAVE' Button Listener
Intent intent = new Intent("USER_NAME_CHANGED_ACTION");
intent.putExtra("username", editText.getText().toString());
// put your all data using put extra
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
For more information on localBroadcastManager look here.
I do not understand why you need this, but you can do it by saving the value of EditText in ActivityC in SparedPreferences here is an example how can make it. Then you should check in onResume() method of ActivityAif there is saved value in SparedPreferences and if has some get the value and set it to "Username" TextView.
EventBus will solve your problem
http://greenrobot.org/eventbus/
I Have a Expendable Listview that a have product list in its child. And every child have two button for add to cart and remove for particular product.
How can i know which product user wants to add.
If i understand your question, i think that if you have your buttons inside xml layout file, you can add an id for each button.
And when you go to process what button is clicked, you can match the id of clicked button with the id of layout.
Hope this help.
use this method in your adapter
private void sendMessage(String duration, String puStatus) {
Log.d("sender", "Broadcasting message");
Intent intent = new Intent("updateDuration");
// You can also include some extra data.
intent.putExtra("duration", duration);
intent.putExtra("puStatus", puStatus);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
use this code in your activity
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String duration = intent.getStringExtra("duration");
String puStatus = intent.getStringExtra("puStatus");
Utilz.printLog("BroadcastReceiver", "Got message: " + duration + " puStatus " + puStatus);
}
};
register receiver in your activity like this
LocalBroadcastManager.getInstance(mContext).registerReceiver(mMessageReceiver,
new IntentFilter("updateDuration"));
How can I update ListView in the other Fragment?
public class ChooseCS extends FragmentActivity {
final private Context context = this;
private HashMap<String, List<String>> mCitiesStreets = null;
private View rootViewStreetChangeFragment = null;
private SimpleAdapter adapter;
...
private static final int NUM_PAGES = 3;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
...
and two Fragments
public class CityChangeFragment extends Fragment {
and
public class StreetChangeFragment extends Fragment {
...
mMapDataAdapter.put("streets", fillcities);
adapter = new SimpleAdapter(
rootViewStreetChangeFragment.getContext(),
mMapDataAdapter.get("streets"), R.layout.grid_streets_4_7,
from, to);
mDataListViewStreets.setAdapter(adapter);
...
I need make update ListView in StreetChangeFragment from CityChangeFragment where I doing changing data
You can use LocalBroadcastManager to achieve this.
In your StreetChangeFragment write below code
#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);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
And use below method to send broadcast message from CityChangeFragment to StreetChangeFragment
private void sendMessage() {
Log.d("sender", "Broadcasting message");
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);
}
Note: You can pass data using intent (here you can position also on which you want to update data in listview)
You can check below link to learn more about LocalBroadcastManager
https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
Interface is good idea,The idea is basically to define an interface and let the activity implement that interface.
Once it has implemented that interface, you could do anything you want in the method it overrides.
There is a good tutorial on Simple Developer Blog how to do exactly this kind of thing.
And you need t declare a method in fragment and it can be executed from the activity by getting the fragment instance from adapter like
Fragment fragment= mPagerAdapter.getItem(int positon);
((StreetChangeFragment )).updateList();
in StreetChangeFragment declare method and do what else you want, Thank you
I'm uploading a large image that is converted to Base64 String in a IntentService. I have splitted the String, to not send all the parts on one time.
In my IntentService so, I'm uploading that parts to the Server.
This happens in the background. If the user wants to know how far the uploading process is, I want to add an Item in the Navigation Drawer to start an Activity that shows the progress.
Is it anyway possible to show this progress?
I would be really thankful if someone can tell me how to do this.
I've read somewhat about BroadcastReceiver. But I don't understand how that works and I really don't know if it will matter my concern.
Thanks for any help!
Kind Regards!
Ofcourse you can use broadcast receivers for this. There is another approach. You can use ResultReceiver class to achieve this. Create a CustomResultReceiver class
public class CustomResultReceiver extends ResultReceiver {
private Receiver receiver;
public CustomResultReceiver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
public interface Receiver {
void onReceiveResult(int resultCode, Bundle resultData);
}
public void setReceiver(Receiver receiver) {
this.receiver = receiver;
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (receiver != null) {
receiver.onReceiveResult(resultCode, resultData);
}
}
}
In your activity, implement the receiver
public class SomeActivity extends Activity implements CustomResultReceiver.Receiver {
public CustomResultReceiver mReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReceiver = new CustomResultReceiver(new Handler());
mReceiver.setReceiver(this);
//pass the receiver to the service
intent.putExtra("SOME_TAG", mReceiver);
}
#Override
public void onReceiveResult(int resultCode, Bundle resultData) {
// here you can get the values from the bundle and display the progress accordingly
}
}
Now in your service, whenever you want to send any data to the activity, you can simple do it by
#Override
protected void onHandleIntent(Intent intent) {
ResultReceiver receiver = intent.getParcelableExtra("SOME_TAG");
Bundle b= new Bundle();
//put your progress value in the bundle
b.putString("SOME_DATA", dataValue);
receiver.send(RESULT_CODE, b);
}
Well I would suggest you to upload you image using AsyncTask. Here you will get the benefit of onProgressUpdate() method. What you need to do is:
Create an interface, having a method, say onUploadingUpdate.
Implement that interface in your activity.
Create your AsyncTask class for uploading your image file.
Call this AsyncTask in your activity using its constructor.
In AsyncTask's onProgressUpdate() method call the interface's method. This will give you the progress in activity.
In Activity use this progress to update progress in your navigation drawer.
If you don't understood, post your code. I'll do it for you.
I'm writing a GCM application.
I'm unable to set a received message to a text view.
Check the below code:
public class GcmMessageHandler extends IntentService {
String mes;
private Handler handler;
public GcmMessageHandler() {
super("GcmMessageHandler");
}
#Override
public void onCreate() {
super.onCreate();
handler = new Handler();
}
#Override
public void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
mes = extras.getString("title");
showMsg();
Log.i("GCM", "Received : (" +messageType+") "+extras.getString("title"));
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
public void showMsg(){
handler.post(new Runnable() {
public void run() {
TextView textview = (TextView)findViewById(R.id.getMsg);
textview.setText(mes );
}
});
}
}
(Error msg : The method findViewById(int) is undefined for the type new Runnable(){})
What you're trying to do is to get the reference of your TextView R.id.getMsg in the layout. You're using the findViewByIdmethod in an IntentService Class which does not provide this method. See Android Documentation
Normally you do that in an Activity or Fragment in lifecycle methods like onCreate or onCreateView etc. where the View is given as parameter value. That looks similar to the following line of code:
TextView textview = (TextView)view.findViewById(R.id.getMsg);
After you've retrieved your TextView reference, you're able to use it in implemented methods.
You need a way to handle data from your Intent Service back to your Application/Activity etc. A possible solution could be to pass your retrieved message data from the IntentService back to the Activity you could use a BroadcastReceiver (as shown here)
Your textview is in service class and textview must be at activity
class . If you want to set data in activity than create an interface
or make textview public static.