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.
Related
I would like to get voice recognition using just one method.
In order to do that i've created 3 classes
the main class
public class Index extends Activity {
private Button boton;
private EditText texto;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
boton = (Button)findViewById(R.id.boton);
texto = (EditText) findViewById(R.id.texto);
boton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
texto.setText(IVRecognition.getInstancia().getComando(Index.this));
}
});
}
}
the intermediate
public class IVRecognition {
//*******************singleton********************
private static IVRecognition instancia;
private IVRecognition (){}
public static IVRecognition getInstancia(){
if (instancia==null) instancia = new IVRecognition();
return instancia;
}
//************************************************
public static String resultado = null;
public String getComando(Context content){
Intent intent = new Intent(content, VRecognition.class);
content.startActivity(intent);
//pause here untill VRecognition.onActivityResult is executed
return resultado;
}
}
and the recognition one
public class VRecognition extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startRecognition();
}
public void startRecognition (){
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,this.getPackageName());
startActivityForResult(intent, 1 /*VOICE_RECOGNITION_REQUEST_CODE*/);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 1 /*VOICE_RECOGNITION_REQUEST_CODE*/ && resultCode == RESULT_OK){
ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
IVRecognition.getInstancia().resultado = result.get(0);
}
this.finish();
}
}
The problem is that when I call VRecognition activity using content.startActivity(intent); the execution of the aplication keeps on going, so the variable called resultado has null value until onActivityResult is executed, which results in a null return value.
Hope you can help me. Cheers
Ian's answer is good. But from your comment, I'd recommend using an IntentService and the BroadcastManager. That way you don't need the intermediate activity. You call the startService(intent) from any activity that wants the VR result (and implements BroadcastReceiver). Then the IntentService calls startActivityForResult(intent,1) and Broadcasts the result.
More info:
http://developer.android.com/training/run-background-service/index.html
It sounds like you want to pause execution until voice recognition is complete. You may want to rethink this; you're calling getComando() from your UI thread, so your application UI will be frozen until recognition is complete. In the (probably quite likely) event that recognition takes more than five seconds, the system will pop up an Application Not Responding dialog. (Also, since you're implementing getComando() by starting another activity within your process, blocking the UI thread in getComando() would prevent recognition from ever running.)
The right way to do this is to use a completion callback. For instance, you could create an IVRecognitionListener interface:
public interface IVRecognitionListener {
public void onRecognitionComplete(String resultado);
}
and pass an instance of that to getComando(). Then instead of just setting IVRecognition.resultado in onActivityResult(), you could call onRecognitionComplete() to notify the caller of the result.
Im just wondering what would be the best and possibly easiest way to do this. I have two activites LoginAcitivty and Main Activity.
Ive coded an AsyncTask in my MainActivity as an inner class which sends updates to a web service. When i click the logout button of the MainActivity this returns the app to the Login Activity. Is it possible to still run the ASyncTask even though there is a different activity running or is there another way to do something like this?
Any suggestions would be greatly appreciated
Thanks
The Asynctask is tied to the "Entity" that created it, in your case it would be the MainActivity, so it will not survive the destroy of your activity (I trust you call the finis() method of the main activity once the user logs out)
What you can do is use a service that runs in background and use the async task to poll your server:
The service shall look like this:
public class PollService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
public void onStart(Intent intent, int startId) {
(new PollAsyncTask(this)).execute();
}
//callback used to retrieve the result from the asynctask
void callBack(String result) {
//here is your logic, taking the result back from the async task
//eventually re-run the asynctask
(new PollAsyncTask(this)).execute();
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
The AsyncTask shall look like this:
private class PollAsyncTask extends AsyncTask<String, Void, String> {
private PollService caller;
PollAsyncTask(PollService caller) {
this.caller = caller;
}
#Override
protected String doInBackground(String... params) {
//do your polling here and return something meaningful to the service,
return SOMETHING_REFERRING_TO_THE_1_OF_3;
}
#Override
protected void onPostExecute(String result) {
//Give the result back to the caller:
this.caller.callBack(result);
}
#Override
protected void onPreExecute() {//nothing special here}
#Override
protected void onProgressUpdate(Void... values) {//nothing special here}
}
That way your async task will poll your server whatever activity is currently in foreground.
The service shall be started by your first activity when it is run the first time (i.e. in the onCreate method):
#Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState==null) {//only the first time
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.yourcompany....PollService");
startService(serviceIntent);
}
}
Hope this helps.
For what I understand, you have an inner Class in your MainActivity.
So just make your AsyncTask in a separate Class and you can call it from both Activites.
Like: new YourAsyncTask().execute();
Greetings.
I make a simple Android Apps that will update its view when an SMS is received. This is the code for my receiver class
public class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
intent.setClass(context, SMSReceiverService.class);
intent.putExtra("result", getResultCode());
WakefulIntentService.sendWakefulWork(context.getApplicationContext(), intent);
}
}
That class will call SMSReceiverService class to handle the oncoming SMS and execute method notifyMessageReceived, which is shown below.
private void notifyMessageRecevied(SMS message) {
if(!isInMyApps()) {
launchPopUp();
}
else {
//updating view should go here
}
}
The problem is, I don't know how to update the view in my activity (which is in separate class, not the SMSReceiverService class), when I tried to update my TextView in my activity, it thrown an CalledFromWrongThreadException. Can anybody please help me ?
Thanks in advance, and sorry about my bad English...
You can create an activity variable to hold the instance of the activity you want.
In SMSReceiver (the one you want to call):
SMSReceiverService.setMainActivity(this);
In SMSReceiverService (the one you want to update from):
public static SMSReceiver smsActivity;
public static void setMainActivity(SMSReceiver activity)
{
smsActivity = activity;
}
...
smsActivity.runOnUiThread(new Runnable() {
public void run() {
try{
smsActivity.textView.setText("");
}
catch{}
}
}
Assuming SMSActivity is the file that contains the view you want to update.
Assuming the service has Context of User Activity
Activity a=(Activity)userContext;
a.runOnUiThread(/*runnable method of activity which calls UpdateView() */);
I currently have a tabhost with 5 tabs. Over one of the tabs I have an ImageView that when the tabs are created it pulls data via POST to display a number. I am wondering how from one of the tab activities (say Rate.java) I could call that method to update that ImageView that is over one of the tabs.
I know it's not very specific but I think I wrote it so you know what I am talking about.
Let me know if you require anymore info.
talitore
Based on the information given, two options that immediately come to mind are:
Send a broadcast from the tab activity (e.g. Rate.java) and have the activity hosting the ImageView listen for it.
Create some sort of BaseActivity (extending Activity) that takes a custom Listener interface with an update method. Have your tab activities extend that BaseActivity and the activity with your ImageView implement it. You can then call the update method on the listener from your tab activities (instantiate them as a BaseActivity and pass along the listener) and make the activity with the ImageView act upon it.
//Edit per request:
A good starting point for information about broadcasts and receivers is the documentation for the BroadcastReceiver. In your case it's probably easiest to just create them in code.
A minimal example will contain something like the following:
BroadcastSendingActivity:
public class BroadcastSendingActivity extends Activity {
public static final String UPDATE_IMAGEVIEW = "UPDATE_IMAGEVIEW";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sender);
Intent i = new Intent();
i.setAction(UPDATE_IMAGEVIEW);
sendBroadcast(i);
}
}
BroadcastReceivingActivity:
public class BroadcastReceivingActivity extends Activity {
private BroadcastReceiver mReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.receiver);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver();
}
#Override
protected void onResume() {
super.onResume();
registerReceiver();
}
private void registerReceiver() {
if (mReceiver == null) {
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BroadcastSendingActivity.UPDATE_IMAGEVIEW)) {
// code to update imageview...
}
}
};
}
getApplicationContext().registerReceiver(mReceiver, new IntentFilter(BroadcastSendingActivity.UPDATE_IMAGEVIEW));
}
private void unregisterReceiver() {
if (mReceiver != null) {
getApplicationContext().unregisterReceiver(mReceiver);
}
}
}
Note that I did not test the code, but I'm sure you'll be able to figure out any mistakes I might've made. :)
I have a main activity that hold the tabs and each tab start a new activity. May I know how can I change the tab title from the new activity? Thanks.
Although CommonsWare has pointed out that having Activities as Tab content is deprecated, if you still want to do it then one possibility is to use a nested BroadcastReceiver and have the content Activity send a broadcast Intent. I'm not sure if it will work but I would try something like the following...
public class MainActivity extends Activity {
bool tabMonitorIsRegistered = false;
TabMonitor tabMonitor = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code
tabMonitor = new TabMonitor();
}
#Override
protected void onResume() {
super.onResume();
if (!tabMonitorIsRegistered) {
registerReceiver(tabMonitor, new IntentFilter(Intent.com.mydomain.myapp.ACTION_TAB_CHANGE));
tabMonitorIsRegistered = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (tabMonitorIsRegistered) {
unregisterReceiver(tabMonitor);
tabMonitorIsRegistered = false;
}
}
// Nested BroadcastReceiver
private class TabMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// Process the Intent here to change the tab title
}
}
}
At this point it occurs to me that each 'content' Activity will need to tell the MainActivity (via the Intent it sends) 'who' it is. To do this, I would use an Intent extra when adding the tab content Activities identifying each as 'tab1', tab2' etc. When the 'content' Activities start, e.g., in onCreate(), they can store this string and use it in the Intent they send as the broadcast to the MainActivity.