Android AsyncTask ProgressDialog rotation different configurations - android

I have managed to use an Asynctask with an indeterminate progress bar during screen rotation. Asynctask starts only once, progress bar is restored on rotation just as I wanted.
I have different layouts for portrait and layout orientations. Layouts include a button and a textview. The size and text color of textview in layout-land is different. And the orientation is landscape.
The problem is when I rotate the screen while asynctask is running, it cant update the textview in onPostExecute method. When I rotate, it recreates the activity with layout-land file. But why I cant update my Textview?
layout\activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startClicked"
/>
<TextView
android:id="#+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
tools:context=".MainActivity" />
</LinearLayout>
layout-land\activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startClicked"
/>
<TextView
android:textSize="36dp"
android:textColor="#ff0000"
android:id="#+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
tools:context=".MainActivity" />
</LinearLayout>
MainActivity.java:
package com.example.asynctaskconfig;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
static String data;
static ProgressDialog pd;
MyAsyncTask task;
TextView tv;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.hello);
if (getLastNonConfigurationInstance() != null) {
task = (MyAsyncTask) getLastNonConfigurationInstance();
if (task != null) {
if (!(task.getStatus().equals(AsyncTask.Status.FINISHED))) {
showProgressDialog();
}
}
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (pd != null)
pd.dismiss();
if (task != null)
return (task);
return super.onRetainNonConfigurationInstance();
}
private void showProgressDialog() {
if (pd == null || !pd.isShowing()) {
pd = new ProgressDialog(MainActivity.this);
pd.setIndeterminate(true);
pd.setTitle("DOING..");
pd.show();
}
}
private void dismissProgressDialog() {
if (pd != null && pd.isShowing())
pd.dismiss();
}
public class MyAsyncTask extends AsyncTask<String, Void, Boolean> {
#Override
protected void onPreExecute() {
showProgressDialog();
}
#Override
protected Boolean doInBackground(String... args) {
try {
Thread.sleep(5000);
data = "result from ws";
} catch (Exception e) {
return true;
}
return true;
}
protected void onPostExecute(Boolean result) {
if (result) {
dismissProgressDialog();
updateUI();
}
}
}
private void updateUI() {
tv.setText(data == null ? "null" : data);
}
public void startClicked(View target) {
task = new MyAsyncTask();
task.execute("start");
}
}

What I have done is as follows:
1- Add android:freezesText="true" to all my TextViews. This enables TextViews to save their states on configuration changes.
2- Make your AsyncTask a static inner class.
3- Modify AsyncTask to keep a reference to the Activity it lives in. So AsyncTask can access UI widgets of Activity via this reference.
4- Here, it is important to keep a valid activity reference during screen rotations. So, override onDestroy method and unbind the Activity from AsyncTask. Thus, task wont keep the old(died) activity.
5- In onRetainNonConfigurationInstance, if task is still running, update its activity reference with the current activity, so it is successfully tied to new activity.
6- Finally, in onPostExecuteMethod, access the UI elements of the Activity via activity reference.
Complete Working Solution:
layout\activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startClicked"
/>
<TextView
android:freezesText="true"
android:id="#+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
tools:context=".MainActivity" />
</LinearLayout>
layout-land\activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startClicked"
/>
<TextView
android:freezesText="true"
android:textSize="36dp"
android:textColor="#ff0000"
android:id="#+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
tools:context=".MainActivity" />
</LinearLayout>
MainActivity.java:
package com.example.asynctaskconfig;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
static ProgressDialog pd;
MyAsyncTask task;
TextView tv;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.hello);
if (getLastNonConfigurationInstance() != null) {
task = (MyAsyncTask) getLastNonConfigurationInstance();
if (task != null) {
task.activity = this;
if (!(task.getStatus().equals(AsyncTask.Status.FINISHED))) {
showProgressDialog();
}
}
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (task != null) {
task.activity = null;
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (pd != null)
pd.dismiss();
if (task != null)
return (task);
return super.onRetainNonConfigurationInstance();
}
private void showProgressDialog() {
if (pd == null || !pd.isShowing()) {
pd = new ProgressDialog(MainActivity.this);
pd.setIndeterminate(true);
pd.setTitle("DOING..");
pd.show();
}
}
private void dismissProgressDialog() {
if (pd != null && pd.isShowing())
pd.dismiss();
}
static class MyAsyncTask extends AsyncTask<String, Void, String> {
MainActivity activity;
public MyAsyncTask(MainActivity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
activity.showProgressDialog();
}
#Override
protected String doInBackground(String... args) {
try {
Thread.sleep(8000);
return "data from ws";
} catch (Exception e) {
return "exception";
}
}
protected void onPostExecute(String result) {
activity.dismissProgressDialog();
activity.tv.setText(result == null ? "null" : result);
}
}
public void startClicked(View target) {
task = new MyAsyncTask(this);
task.execute("start");
}
}

The problem in your case is essentially that the TextView you are trying to change is no longer the TextView visible on the screen. The rotation caused Android to discard the old Activity and building a new one - complete with all views in the xml file. Thus, your TextView 'tv' is still part of the old activity, changes will just do nothing.
The easiest way now to get the behavior you want, is to just look again for the textview, i.e., use "findViewById" again in your updateUI method and you should be fine!

In this case you probably don't want the activity to be recreated on orientation changes. You may handle the orientation changes within your activity by adding this to your activity in your manifest:
android:configChanges="keyboardHidden|orientation"
Then override onConfigurationChanged:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.hello);
}

Try this instead:
private void updateUI() {
final TextView tv = (TextView) findViewById(R.id.hello);
tv.setText(data == null ? "null" : data);
}
If that fails, is it possibly a timing-issue? That is, could it be the task completed during the orientation change? Just to be on the safe side, you could modify your onCreate method by adding an updateUI() call if task has finished:
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.hello);
if (getLastNonConfigurationInstance() != null) {
task = (MyAsyncTask) getLastNonConfigurationInstance();
if (task != null) {
if (!(task.getStatus().equals(AsyncTask.Status.FINISHED))) {
showProgressDialog();
} else
updateUI();
}
}
}

Related

activity to fragment method calling in a thread with progressbar

I am using this code, everything are working fine, but progressbar is not showing. I want to block my ui during the method implementation and want to show progressbar. I want to get behaviour like progressDialog.
Here is my method
public void effct(int effectNo) {
final int finalEffectNO = effectNo;
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressLayout.setVisibility(View.VISIBLE);
progressLayoutLinear.setVisibility(View.VISIBLE);
Thread thread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
imageViewFragment.applyEffect(finalEffectNO);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressLayout.setVisibility(View.GONE);
progressLayoutLinear.setVisibility(View.GONE);
}
});
}
};
thread.start();
}
My xml code for progressLayout
<LinearLayout
android:id="#+id/progressBarLinearLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:padding="12dp"
android:visibility="gone"
android:orientation="horizontal">
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Loading"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:textSize="18sp"/>
</LinearLayout>
For above your requirement you must use ProgressDialog for same, here is an example
Example
Try using an AsyncTask instead of Thread, something like this :
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
progressLayoutLinear.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(final Void ... params ) {
runOnUiThread(new Runnable() {
#Override
public void run() {
imageViewFragment.applyEffect(finalEffectNO);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
});
return null;
}
#Override
protected void onPostExecute( final Void result ) {
progressLayoutLinear.setVisibility(View.GONE);
}
}.execute();
Hope this helps
There’s a few ways to solve your problem - check this video for more information. The most basic approach might be an AsyncTask, which could look like this:
public class DummyAsyncTask extends AsyncTask<Void, Void, Void> {
private final Window window;
private final ProgressBar progressBar;
public DummyAsyncTask(Window window, ProgressBar progressBar) {
this.window = window;
this.progressBar = progressBar;
}
#Override protected void onPreExecute() {
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressBar.setVisibility(View.VISIBLE);
}
#Override protected Void doInBackground(Void... voids) {
// Do the heavy lifting.
}
#Override protected void onPostExecute(Void aVoid) {
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
progressBar.setVisibility(View.GONE);
}
}
You execute it by running new DummyAsyncTask(/* params */).execute();.
Do note that AsyncTask does not adhere to the lifecycle and holding a reference to a Context aware instance is just asking for trouble. A safer alternative might be using LiveData:
public void effect(int effectNo) {
// Show progress and disable user interaction here.
final ListData<Content> data = model.applyEffect(effectNo);
data.observe(this, (Observer<Content>) c -> {
// Apply results, hide progress & enable user interaction.
});
}
Given the above, you should be careful how you handle showing & hiding progress, so you don’t accidentally disable user interaction forever.

Android Studio Progress Bar Move

I put a progress bar in my android studio project , and want it to move , but i don't know how to do that . I tried to look for tutorials on YouTube and follow along , but that didn't work out for me. Then i looked on google for tutorials but that didn't work for me . When i search them up i only see tutorials with the circle loading bars and I want mine to be horizontal . I only know where to start the loading bar but i really want to know how to make it move and then go into the game . I don't have any code because when i seen that it wasn't working i just deleted it . If anybody has a good tutorial or code that could help me i would appreciate very much . Thanks.
have very easy way to use progress bar within whole code
custom_progressbar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="#+id/progressbar_view"
android:layout_width="#dimen/_70sdp"
android:layout_height="#dimen/_70sdp"
android:indeterminate="true"
android:padding="#dimen/_10sdp" />
</RelativeLayout>
CustomProgressBar.java
public class CustomProgressBar extends Dialog {
Activity activity;
public CustomProgressBar(Activity act) {
super(act);
this.activity = act;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.custom_progressbar);
setCancelable(false);
// set backgroung transparent
getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
}
and apply whenever you want activity or fragment
public CustomProgressBar customProgressBar;
customProgressBar = new CustomProgressBar(context);
customProgressBar.show();
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
private TextView loading;
private int progressStatus = 0;
private Handler pHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
loading = (TextView) findViewById(R.id.loading);
new Thread(new Runnable() {
#Override
public void run() {
while (progressStatus < 100) {
progressStatus ++;
android.os.SystemClock.sleep(50);
pHandler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(progressStatus);
}
});
}
pHandler.post(new Runnable() {
#Override
public void run() {
loading.setText("COMPLETE");
}
});
}
}).start();
}
This code works. You should be able to use the default XML code for the ProgressBar. You will need to add the elements, for example, the actual progress bar in the visual design. You will need to add an extra '}' at the end I think.
Check this: Infact you have to code for the horizontal progress bar movement and set its progress, it's specially used in downloading to show percentage of operation completion.
XML code:
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="23dp"
android:layout_marginTop="20dp"
android:indeterminate="false"
android:max="100"
android:minHeight="50dp"
android:minWidth="200dp"
android:progress="1" />
java code:
public class MainActivity extends Activity {
private ProgressBar progressBar;
private int progressStatus = 0;
private TextView textView;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
textView = (TextView) findViewById(R.id.textView1);
//Long operation by thread
new Thread(new Runnable() {
public void run() {
while (progressStatus < 100) {
progressStatus += 1;
//Update progress bar with completion of operation
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items
//to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="50">
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"
android:id="#+id/Bar1"
android:max="10"
android:padding="15dp"
android:paddingTop="5dp"
android:paddingRight="20dp"
android:paddingLeft="20dp">
</ProgressBar>
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startProgress"
android:text="Start" />
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar2"
android:layout_gravity="center_horizontal" />
</LinearLayout>
MainActivity.java
package com.example.dell.vlakna;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import static com.example.dell.vlakna.R.layout.activity_main;
public class MainActivity extends Activity {
private ProgressBar bar;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_main);
bar = (ProgressBar) findViewById(R.id.Bar1);
}
public void startProgress(View view) {
bar.setProgress(0);
new Thread(new Task()).start();
}
class Task implements Runnable {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bar.setProgress(value);
}
}
}
}
this code run good.

White bar appears behind progress indicator

My loading circle works fine but has a white box behind it as seen here. I have spent a few hours searching for solutions and all of the SO posts I've found suggest an implementation very similar to the one I've used. I also tried applying a custom theme to the dialog and setting transparency but this did nothing. I'm not sure what the white rectangle actually is since changing the properties of the ProgressBar itself only seems to affect the square in the center containing the image.
I have the following layout defined for my progress bar which runs during my AsyncTask.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#android:color/transparent" >
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"/>
</FrameLayout>
Below is my method for the dialog which uses the layout shown above.
public static ProgressDialog createProgressDialog(Context mContext) {
ProgressDialog dialog = new ProgressDialog(mContext);
try {
dialog.show();
} catch (WindowManager.BadTokenException e) {
}
dialog.setCancelable(false);
dialog.setContentView(R.layout.progressdialog);
return dialog;
}
public class FetchAcroTask extends AsyncTask<String, Void, String[]> {
Dialog progressDialog = null;
#Override
protected void onPreExecute() {
// Display loading circle
if (progressDialog == null) {
progressDialog = createProgressDialog(AcroActivity.this);
progressDialog.show();
} else {
progressDialog.show();
}
}
#Override
protected String[] doInBackground(String... params) {
if (params.length == 0) {
return null;
}
return GET(params[0]);
}
#Override
protected void onPostExecute(String[] resultStrs) {
if (resultStrs == null) {
acroAdapter.add("No results were found");
} else {
acroAdapter.addAll(resultStrs);
}
// Dismiss loading circle
progressDialog.dismiss();
}
}
}
Thanks in advance.
I've found the solution thanks to the comment left by Kostas.
I transferred my ProgressBar declaration to my layout file for the activity and simply hide it when my AsyncTask is complete.
In my activity's layout file:
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
Within the async task:
#Override
protected void onPostExecute(String[] resultStrs) {
if (resultStrs == null) {
acroAdapter.add("No results were found");
} else {
acroAdapter.addAll(resultStrs);
}
// Dismiss loading circle
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
progressBar.setVisibility(View.INVISIBLE);
}
Thank you.

Trouble getting handle to TextView in android callback

I am trying to make a remote control for a Google TV.
I want to change the text I have in a layout (TextView statusText) with connected when the device has successfully connected. But I get an exception when I try to do this:
"07-07 22:42:20.870: E/AndroidRuntime(5750):android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
"Appreciate any help/pointers
Here is my MainActivity.java and main.xml:
MainActivity.java:
package uk.co.mypack.gtvremote;
//imports removed for paste
public class MainActivity extends Activity implements ClientListener{
private AnymoteSender anymoteSender;
private TextView statusText;
protected AnymoteClientService mAnymoteClientService;
private static String statusPrefix = "Status: ";
private Context mContext;
private ProgressBar progressBar;
private Handler handler;
private TouchHandler touchPadHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progressBar = (ProgressBar) findViewById(R.id.a_progressbar);
progressBar.setVisibility(View.VISIBLE);
mContext = this;
ImageButton upArrowButton = (ImageButton) findViewById(R.id.upArrow);
ImageButton leftArrowButton = (ImageButton) findViewById(R.id.leftArrow);
ImageButton centreButton = (ImageButton) findViewById(R.id.centreButton);
ImageButton rightArrowButton = (ImageButton) findViewById(R.id.rightArrow);
ImageButton downArrowButton = (ImageButton) findViewById(R.id.downArrow);
upArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_UP);
}
});
leftArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
}
});
centreButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_CENTER);
}
});
rightArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
}
});
downArrowButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
sendKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN);
}
});
handler = new Handler();
// Bind to the AnymoteClientService
Intent intent = new Intent(mContext, AnymoteClientService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
statusText = (TextView) findViewById(R.id.statusText);
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
/*
* ServiceConnection listener methods.
*/
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAnymoteClientService = ((AnymoteClientService.AnymoteClientServiceBinder) service)
.getService();
mAnymoteClientService.attachClientListener(MainActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mAnymoteClientService.detachClientListener(MainActivity.this);
mAnymoteClientService = null;
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onConnected(AnymoteSender anymoteSender) {
if (anymoteSender != null) {
// Send events to Google TV using anymoteSender.
// save handle to the anymoteSender instance.
this.anymoteSender = anymoteSender;
//THIS IS WHERE I AM TRYING TO SET THE TEXTVIEW
TextView localStatusText = (TextView) findViewById(R.id.statusText);
localStatusText.setText(statusPrefix + "Connected to GoogleTV");
//ABOVE IS WHERE I AM TRYING TO SET THE TEXTVIEW
// Attach touch handler to the touchpad view
touchPadHandler = new TouchHandler(
findViewById(R.id.touchPad), Mode.POINTER_MULTITOUCH, anymoteSender);
} else {
statusText.setText(statusPrefix + "Connection attempt failed, cant find send handler");
//attempt to connect again?
//attemptToConnect();
}
// Hide the progressBar once connection to Google TV is established.
handler.post(new Runnable() {
public void run() {
progressBar.setVisibility(View.INVISIBLE);
}
});
}
#Override
public void onDisconnected() {
// show message to tell the user about disconnection.
statusText.setText(statusPrefix + "Disconnected");
// Try to connect again if needed. This may be need to be done via button
attemptToConnect();
this.anymoteSender = null;
}
#Override
public void onConnectionError() {
// show message to tell the user about disconnection.
statusText.setText(statusPrefix + "Connection error encountered");
// Try to connect again if needed.
attemptToConnect();
this.anymoteSender = null;
}
#Override
protected void onDestroy() {
if (mAnymoteClientService != null) {
mAnymoteClientService.detachClientListener(this);
}
unbindService(mConnection);
super.onDestroy();
}
public void attemptToConnect()
{
//stub to invoke connection attempt
}
private void sendKeyEvent(final int keyEvent) {
// create new Thread to avoid network operations on UI Thread
if (anymoteSender == null) {
Toast.makeText(MainActivity.this, "Waiting for connection",
Toast.LENGTH_LONG).show();
return;
}
anymoteSender.sendKeyPress(keyEvent);
}
}
Main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/control_message"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="#dimen/padding_medium"
android:text="#string/control_msg"
android:textSize="90dp"
tools:context=".MainActivity" />
<LinearLayout
android:id="#+id/middlePanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/statusText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Status: Disconnected - startup"
android:textSize="20dp" />
<ImageView
android:id="#+id/touchPad"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="#drawable/greysquare"
/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageButton
android:id="#+id/upArrow"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/blackuparrow" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ImageButton
android:id="#+id/leftArrow"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/blackleftarrow" />
<ImageButton
android:id="#+id/centreButton"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/emptycircle"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" />
<ImageButton
android:id="#+id/rightArrow"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/blackrightarrow" />
</LinearLayout>
<ImageButton
android:id="#+id/downArrow"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/blackdownarrow" />
</LinearLayout>
</LinearLayout>
<ProgressBar
android:id="#+id/a_progressbar"
style="#android:style/Widget.ProgressBar.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</LinearLayout>
The onConnected() callback is not called on the Main UI thread, but on a separate thread that is used by the Service. So it is not able to access the TextView created in Main UI thread. What you should do is create a Handler in the main UI thread and then use that handler to post a runnable that makes changes to the TextView. You can read more about Handlers on the Android developer site.

Android Show and hide views in AsyncTask

Hi I have a AysncTask that i'm wanting to inflate a loading view whilst that runs when it's finished hide it. does anyone know how to do this? at moment its not showing the loading view.
this is what i have tried
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
loadingView = LayoutInflater.from(getBaseContext()).inflate(R.layout.loadingcell,
null);
//Check Preferences which sets UI
checkPreferences();
PostTask posttask;
posttask = new PostTask();
posttask.execute();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean result = false;
loadFixtures();
publishProgress("progress");
loadResultsFeed();
publishProgress("progress");
loadNewsFeed();
publishProgress("progress");
return result;
}
protected void onProgressUpdate(String... progress) {
StringBuilder str = new StringBuilder();
for (int i = 1; i < progress.length; i++) {
str.append(progress[i] + " ");
}
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
Log.v("BGThread", "begin fillin data");
FillData();
loadingView.setVisibility(View.GONE);
}
}
loadingcell.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/white"
android:id="#+id/loadingcell">
<include
layout="#layout/header" />
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="87dp" />
<TextView
android:id="#+id/textView1"
android:layout_width="115dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/progressBar1"
android:gravity="center"
android:text="Loading..."
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/blue" />
</RelativeLayout>
You are not using an AsyncTask in you code. Use something like this:
private class doSomething extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
//Inflate you view or do anything here before loading stuff
}
protected Void doInBackground(Void... urls) {
//loading stuff
}
protected void onProgressUpdate(String... progress) {
//change your UI - like a progressbar
}
#Override
protected void onPostExecute(String unused) {
//Hide the progressbar
}
You need to have a content for the Activity - which you can set using setContentView

Categories

Resources