Android move from one activity to another - java

I was having some problem for Android activity transition. Basically what I am trying to do is share text to Twitter. However, when I open up the twitter content, it took quite a few seconds to load up the content and resulting in the white blank activity for a few seconds.
And here is my codes, when my button onClick, I am executing the loading dialog:
ivTwitterShare.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Thread newThread = new Thread() {
#Override
public void run() {
try {
super.run();
sleep(10000);
} catch (Exception e) {
} finally {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri
.parse(tweetUrl));
startActivity(intent);
progressDialog.dismiss();
}
}
};
newThread.start();
new LoadTwitterTask().execute();
}
});
private class LoadTwitterTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(context, "Loading Twitter...",
"Retrieving Twitter information, please wait...", false,
false);
EventDialogueBox.customizeDialogueBox(context, progressDialog);
}
#Override
protected Void doInBackground(Void... params) {
try {
synchronized (this) {
int counter = 0;
while (counter <= 4) {
this.wait(50);
counter++;
publishProgress(counter * 25);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void result) {
}
}
However, my problem now is the white blank page before the content is loaded up still there. What I wanted is firstly, the loading dialog will show. Then, at the same time, the twitter intent is loading. Once finish loaded up the content, then dialog will be dismissed.
Any ideas?
Thanks in advance.

Related

Only the original thread that created a view hierarchy can touch its views error in asynctask

I'm using View.OnClickListener. Code is as given below:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.appCompatButtonLogin:
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
break;
case R.id.textViewLinkRegister:
// Navigate to RegisterActivity
Intent intentRegister = new Intent(getApplicationContext(), RegisterActivity.class);
startActivity(intentRegister);
break;
}
}
My AsyncTask class is like this:
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this);
#Override
protected void onPreExecute() {
if (progressDialog == null) {
progressDialog.setIndeterminate(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait!");
progressDialog.show();
}
super.onPreExecute();
}
#Override
protected String doInBackground(String... strings) {
try {
verifyFromSQLite();
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void verifyFromSQLite() {
if (inputValidation.isInputEditTextFilled(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))) {
return;
}
if (inputValidation.isInputEditTextEmail(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))) {
return;
}
if (inputValidation.isInputEditTextFilled(textInputEditTextPassword, textInputLayoutPassword, getString(R.string.error_message_email))) {
return;
}
if (databaseHelper.checkUser(textInputEditTextEmail.getText().toString().trim()
, textInputEditTextPassword.getText().toString().trim())) {
Intent accountsIntent = new Intent(activity, UsersListActivity.class);
accountsIntent.putExtra("EMAIL", textInputEditTextEmail.getText().toString().trim());
emptyInputEditText();
startActivity(accountsIntent);
} else {
Toast.makeText(LoginActivity.this, "Please check your credentials", Toast.LENGTH_SHORT).show();
}
}
private void emptyInputEditText() {
textInputEditTextEmail.setText(null);
textInputEditTextPassword.setText(null);
}
#Override
protected void onPostExecute(String s) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
When I run my code, I get an exception like this:
Only the original thread that created a view hierarchy can touch its views
I'm trying to separate UI from non-UI part in asynctask, how can I fix this?
You can't make changes to UI in a background task.
Move this code:
Intent accountsIntent = new Intent(activity, UsersListActivity.class);
accountsIntent.putExtra("EMAIL", textInputEditTextEmail.getText().toString().trim());
emptyInputEditText();
startActivity(accountsIntent);
and
Toast.makeText(LoginActivity.this, "Please check your credentials", Toast.LENGTH_SHORT).show();
to onPostExecute().
You can set values to boolean flags for these cases in doInBackground() and check them in onPostExecute() and act accordingly.

ProgressDialog new Activity Asynctask is not showing, why?

I made a AsyncTask class with the following code
public class removeDialog extends AsyncTask<Void, Void, Void> {
Context c;
ProgressDialog asyncDialog;
String page;
public removeDialog(Context c, String page) {
this.c = c;
this.page = page;
asyncDialog = new ProgressDialog(c);
}
#Override
protected void onPreExecute() {
//set message of the dialog
asyncDialog.setTitle("Please wait");
asyncDialog.setMessage("Loading...");
asyncDialog.setCancelable(false);
//show dialog
asyncDialog.show();
if (page == "algemeneVoorwaarden") {
Intent intent = new Intent(c, algemeneVoorwaarden.class);
c.startActivity(intent);
}
if (page == "contact") {
Intent intent = new Intent(c, contactTest.class);
c.startActivity(intent);
}
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... arg0) {
//don't touch dialog here it'll break the application
//do some lengthy stuff like calling login webservice
return null;
}
#Override
protected void onPostExecute(Void result) {
//hide the dialog
asyncDialog.dismiss();
super.onPostExecute(result);
}
}
First time I tried:
on the first time I see an ProgressDialog, but the second time I want to open the activity I get nothing.
Second time I tried:
I get no ProgressDialog even the first time I try.
I execute my code in an AsyncTask class, code:
voorwaarden.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new removeDialog(c, "algemeneVoorwaarden").execute();
}
});
Does someone know why it isn't working? Please help me.
Your dialog will be dismissed as soon as it's shown, because your doInBackground is empty. Try adding a Thread.sleep() with a few seconds, just to simulate a delay.
Also, I suspect that the new activities you're starting will leave your dialog behind. So I would suggest you to test the code without these new activities for now.
public class RemoveDialog extends AsyncTask<Void, Void, Void> {
ProgressDialog asyncDialog;
public RemoveDialog(Context c) {
asyncDialog = new ProgressDialog(c);
}
#Override
protected void onPreExecute() {
//set message of the dialog
asyncDialog.setTitle("Please wait");
asyncDialog.setMessage("Loading...");
asyncDialog.setCancelable(false);
//show dialog
asyncDialog.show();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... arg0) {
try {
Thread.sleep(3000);
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
//hide the dialog
asyncDialog.dismiss();
super.onPostExecute(result);
}
}

AsyncTask block Unity(UI) thread issue

Here is my main Activity in OnCreate:
mUnityPlayer = new UnityPlayer(this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
new SimuDownloadTask(this).execute();
The following code is the source code of SimuDownloadTask:
public class SimuDownloadTask extends AsyncTask<Void, Integer, Boolean> {
private ProgressDialog progressDialog;
private int count=0;
private Context mainActivityContext;
public SimuDownloadTask(Context context) {
mainActivityContext=context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog=new ProgressDialog(mainActivityContext,R.style.XMNewDialog);
progressDialog.show();
}
#Override
protected Boolean doInBackground(Void... arg0) {
while(true)
{
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int downloadPercent=doDownload();
publishProgress(downloadPercent);
if(downloadPercent>=500)
break;
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialog.setMessage("current progress:"+values[0]+"%");
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progressDialog.dismiss();
if(result)
{
Toast.makeText(mainActivityContext, "success", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(mainActivityContext, "fail", Toast.LENGTH_SHORT).show();
}
}
private int doDownload()
{
count+=1;
return count;
}
}
Here is the problem. When I start the app, the progressbar blocks the UI thread.
After the progressbar finished, the Unity starts.
When I replace the SimuDownloadTask in OnCreate with the following code:
new Thread(){
#Override
public void run() {
super.run();
Looper.prepare();
progressDialog=new ProgressDialog(UnityPlayerActivity.this,R.style.XMNewDialog);
progressDialog.setTitle("test");
progressDialog.setCancelable(true);
progressDialog.show();
Looper.loop();
}
}.start();
The unity thread is running properly(not blocked by the progressbar). So I think the problem is not relevant to Unity.
I have already checked the relevant links such as:
Asynctask from non ui thread
But still can't figure out the issues.
Any clues will be helpful.
Instead of using an AsyncTask you may use a worker thread for the counter logic and a handler to update the progress bar.
See the updated answer in this link

Queuing images path when there's no internet connection

I'm havin difficulties of keeping track of my queue.
I'm trying to store image-paths into a queue so i can use the queue to start uploading my images once there's internet (at a later moment). The upload image is an asynctask and in the postExecute i'm trying to send a mail with the uploaded picture attached to it in another asynctask.
This is my UploadImage AsyncTask. I think i'm doing way too difficult and that it can be done much easier than it is right now.
private class UploadImageTask extends AsyncTask<Void, Void, Integer> {
ProgressDialog dialog;
/**
* Private integer which counts how many times we've tried to upload the
* Image.
*/
private int _counter = 0;
private List<String> imageUploadList = new ArrayList<String>();
#Override
protected void onPreExecute() {
super.onPreExecute();
if(AppStatus.haveNetworkConnection(_context)){
if(isPhotoTaken()){
dialog = new ProgressDialog(Step4.this);
dialog.setCancelable(false);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(getString(R.string.uploadingMessage));
dialog.setTitle(getString(R.string.uploadingTitle));
dialog.show();
}
}
}
protected Integer doInBackground(Void... params) {
init();
postData();
return null;
}
public void init(){
_counter = 0;
_beenHere = true;
for(String path : imageUploadList){
Debug.out("Path: "+path);
}
}
public void postData() {
if (isPhotoTaken()) {
if(AppStatus.haveNetworkConnection(_context)){
if(_beenHere){
ImageUploader.uploadFile(getPhotoPath(),
"http://obo.nl/android-upload-image.php", Step4.this);
} else {
for(String path : imageUploadList){
Debug.out(path);
ImageUploader.uploadFile(path,
"http://obo.nl/android-upload-image.php", Step4.this);
}
}
} else {
if (_counter == 0) {
_counter++;
_activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(_context,
getString(R.string.noInternetImageNotUploaded),
Toast.LENGTH_LONG).show();
}
});
imageUploadList.add(getPhotoPath());
}
try {
if(_beenHere){
_beenHere = false;
goToNextIntent();
}
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
postData();
}
}
}
private void goToNextIntent(){
Intent intent = new Intent(Step4.this, Step5.class);
intent.putExtra(EXTRA_MESSAGE, (Serializable) _user);
intent.putExtra(EXTRA_MESSAGE2, _isRepairable);
intent.putExtra(EXTRA_MESSAGE3, _injury);
intent.putExtra(EXTRA_MESSAGE4, _category);
intent.putExtra(EXTRA_MESSAGE5, _inch);
intent.putExtra(EXTRA_MESSAGE6, _size);
startActivity(intent);
}
protected void onPostExecute(Integer result) {
if(isPhotoTaken()){
if(dialog != null){
dialog.dismiss();
}
}
mailing(_isRepairable);
new MyAsyncTask().execute(_mail);
}
}
The line:
if(AppStatus.haveNetworkConnection(_context))
returns a boolean true if the user has a working internet connection. false otherwise.
What I want is to queue all the image paths (and mails sent afterwards) in the desired ArrayList so i can send them all at a later moment when the user has a working internet Connection. Please help me out!

Can't create handler inside thread that has not called Looper.prepare()

I get this error "Can't create handler inside thread that has not called Looper.prepare()"
Can you tell me how to fix it?
public class PaymentActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.payment);
final Button buttonBank = (Button) findViewById(R.id.buttonBank);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = ProgressDialog.show(PaymentActivity.this, "",
"Redirecting to payment gateway...", true, true);
new Thread() {
public void run() {
try {
startPayment("Bank");
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
}
}.start();
}
});
StartPayment Method:
private void startPayment(String id) {
Bundle b = getIntent().getExtras();
final Sail sail = b.getParcelable(Constant.SAIL);
final Intent bankIntent = new Intent(this, BankActivity.class);
try {
Reservation reservation = RestService.createReservation(
sail.getId(),
getSharedPreferences(Constant.PREF_NAME_CONTACT, 0));
bankIntent.putExtra(Constant.RESERVATION, reservation);
// <workingWithDB> Storing Reservation info in Database
DBAdapter db = new DBAdapter(this);
db.open();
#SuppressWarnings("unused")
long rowid;
rowid = db.insertRow(sail.getId(), sail.getFrom(),
sail.getTo(), sail.getShip(), sail.getDateFrom().getTime(),
sail.getPrice().toString(), reservation.getId().floatValue());
db.close();
// </workingWithDB>
String html = PaymentService.getRedirectHTML(id, reservation);
bankIntent.putExtra(Constant.BANK, html);
} catch (Exception e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog.setMessage(e.getMessage());
alertDialog.show();
}
startActivity(bankIntent);
}
You should know that when you try to modify your UI , the only thread who can do that is the UiThread.
So if you want to modify your UI in another thread, try to use the method: Activity.runOnUiThread(new Runnable);
Your code should be like this :
new Thread() {
public void run() {
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
try {
startPayment("Bank");//Edit,integrate this on the runOnUiThread
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
});
}
}
}.start();
I assume you create a Handler in startPayment() method. You can't do that, as handlers can be created on th UI thread only. Just create it in your activity class.
Instead of new Thread() line, try giving
this.runOnUiThread(new Runnable() {
you cant change any UI in thread you can use runOnUIThread or AsyncTask for more detail about this click here
I've found that most thread handling can be replaced by AsyncTasks like this:
public class TestStuff extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonBank = (Button) findViewById(R.id.button);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new StartPaymentAsyncTask(TestStuff.this).execute((Void []) null);
}
});
}
private class StartPaymentAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog dialog;
private final Context context;
public StartPaymentAsyncTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(context.getString(R.string.doing_db_work));
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(Void... ignored) {
String returnMessage = null;
try {
startPayment("Bank");
} catch (Exception e) {
returnMessage = e.getMessage();
}
return returnMessage;
}
#Override
protected void onPostExecute(String message) {
dialog.dismiss();
if (message != null) {
// process the error (show alert etc)
Log.e("StartPaymentAsyncTask", String.format("I received an error: %s", message));
} else {
Log.i("StartPaymentAsyncTask", "No problems");
}
}
}
public void startPayment(String string) throws Exception {
SystemClock.sleep(2000); // pause for 2 seconds for dialog
Log.i("PaymentStuff", "I am pretending to do some work");
throw new Exception("Oh dear, database error");
}
}
I pass in the Application Context to the Async so it can create dialogs from it.
The advantage of doing it this way is you know exactly which methods are run in your UI and which are in a separate background thread. Your main UI thread isn't delayed, and the separation into small async tasks is quite nice.
The code assumes your startPayment() method does nothing with the UI, and if it does, move it into the onPostExecute of the AsyncTask so it's done in the UI thread.
Try
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable() {
public void run() {
......
}
}, time_interval});

Categories