DI have a GLES20 glsurfaceview that sends an fps status string to my main activity via a messageHandler which I want to display on the screen while the GL is running.
public static Handler messageHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
String message = (String)msg.obj;
Globals.stats.setText(message);
Globals.stats.setVisibility(View.VISIBLE);
Globals.stats.invalidate();
}
};
Global.stats points to an onscreen textview.
During the time the GLES code is running and updating the screen the textview does not display. Once the GL rendering stops the textview does update with the last sent message and appears.
Is there anyway I can tell OpenGL or the surfaceview to yield and allow all the UI elements to update before continuing?
The layout is a relative layout with the textview on it, ie
<RelativeLayout
android:id="#+id/mainContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:background="#ff000000"
android:gravity="fill">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/statsTextView"
android:textColor="#ffffffff"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:background="#80000000" />
</RelativeLayout>
The GLES code is taken from many examples on the web. A glsurf class
public class GLSurf extends GLSurfaceView {
private final GLRenderer mRenderer;
public GLSurf(Context context) {
super(context);
setEGLContextClientVersion(2);
mRenderer = new GLRenderer(context);
setRenderer(mRenderer);
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
#Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
mRenderer.onPause();
}
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
mRenderer.onResume();
}
}
And a public class
GLRenderer implements Renderer {
class that uses the
public void onDrawFrame(GL10 unused) {
to draw the GLES output and then uses
MainActivity.messageHandler.sendMessage(msg);
to send the fps status.
Is there any better way to get the textview to update while the GLES is running? The message does get sent and received because once the GL stops the textview is updated with the latest frame number and fps info.
Related
I am working on an Android app that is behaving oddly. One of the first things this app does upon start up, is to start a listening thread that listens to a "server" app, on the same device, to get data. Once this data is received by the listening thread, I use it to update the main view. This, however only works if my app is started after the server app.
First a few details. My app and the server app are on the same device. They communicate with each other via UDP (the server app is a port of a Windows application). My app uses fragments, but the view I want to update is not within a fragment. Now some code.
content_main.xml
<RelativeLayout>
<LinearLayout>
<ImageView
android:id="#+id/my_image_id"
android:src="#drawable/my_image" />
</LinearLayout>
<LinearLayout>
<!-- fragment code here -->
</LinearLayout>
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState){
Listener myListener = new Listener(this);
Thread listenerThread = new Thread(myListener);
listenerThread.setName("My Listener Thread");
listenerThread.start();
}
}
Listener.java
public class Listener implements Runnable {
public Listener (Activity mainActivity) {this.mainActivity = mainActivity;}
private Activity mainActivity;
private ImageView myImageView;
private NewData newData;
#Override
public void run(){
while(true){
// Here is where my app gets the data from the server via UDP.
// This always works, I am always getting the correct data.
myImageView = (ImageView) mainActivity.findViewById(R.id.my_image_id);
mainActivity.runOnUiThread(new Runnable(){
#Override
public void run(){
if(newData == 1){
myImageView.setImageResource(R.drawable.new_image_01);
} else if(newData == 2){
myImageView.setImageResource(R.drawable.new_image_02);
} else {
myImageView.setImageResource(R.drawable.error_image);
}
}
});
}
}
}
Like I said, if I start my app after the server app, then this all works perfectly. The images always changes when the new data changes. However, if I start my app before the server app, or if I restart the server app while my app is still running, then the images never changes, even though I am still getting the correct data from the server app.
What can I do to make sure the view can update at any time?
EDIT: I moved where I get the view to outside of the while loop (as a test) and now the code doesn't work at all.
I gave it a try. apparently your code is working alright, if the thread starts after the activity is been initialized, i don't really know how your server app works so i tried to mimic something like this.
public class TestThreadActivity extends AppCompatActivity {
private Button restart_Button;
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_thread);
Toolbar toolbar = (Toolbar) findViewById(R.id.my_custom_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
initializeUI();
}
private void initializeUI() {
restart_Button = (Button) findViewById(R.id.TestThreadActivity_restart_button);
imageView = (ImageView) findViewById(R.id.TestThreadActivity_imageView);
final Listener myListener = new Listener(this);
restart_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageView.setImageResource(R.drawable.piccolo);
final Thread listenerThread = new Thread(myListener);
listenerThread.setName("My Listener Thread");
listenerThread.start();
}
});
}
public class Listener implements Runnable {
public Listener (Activity mainActivity) {this.mainActivity = mainActivity;}
private Activity mainActivity;
private ImageView myImageView;
int newData = 0;
#Override
public void run(){
while(true){
// Here is where my app gets the data from the server via UDP.
// This always works, I am always getting the correct data.
newData = (new Random()).nextInt(3);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myImageView = (ImageView) mainActivity.findViewById(R.id.TestThreadActivity_imageView);
mainActivity.runOnUiThread(new Runnable(){
#Override
public void run(){
System.out.println("newData: "+newData);
if(newData == 1){
myImageView.setImageResource(R.drawable.gohan);
} else if(newData == 2){
myImageView.setImageResource(R.drawable.goku);
} else {
myImageView.setImageResource(R.drawable.piccolo);
}
}
});
}
}
}
}
activity_test_thread.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"
tools:context="activities.list.first.TestThreadActivity">
<include layout="#layout/my_custom_toolbar" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="#+id/TestThreadActivity_restart_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_weight="0.5"
android:text="Start"
android:contentDescription="this will restart the thread"
android:textAllCaps="false" />
</LinearLayout>
<ImageView
android:id="#+id/TestThreadActivity_imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="#drawable/gohan" />
</LinearLayout>
</LinearLayout>
Output
There are multiple similar questions like mine, but these questions didn't help me.
I'm making a game. The game thread, SurfaceView and Activity is already finished and works so far. The problem is that the canvas is not redrawn. At startup, it draws the icon on the background, but at every tick, the icon doesn't move (It should move once a second). I want to mention, that I never needed to call postInvalidate. I have a working example where I never called it, but it doesn't work in my current example (I don't want to go into it deeper, since I actually don't need to call it). I copied the current code from my working example, the concept and the way of implementation is exactly the same, but my current code doesn't refresh the canvas. When I log the drawing positions in onDraw method, I see that it's coordinates are updated every second as expected, so I can be sure it's a canvas drawing problem. I have searched for hours but I didn't find what's different to my working example (except that I'm using another Android version and I don't extend thread but implement Runnable, because it's a bad style to extend thread. Nevertheless, I also extended thread to see if there is any difference, but it doesn't help). I already tried to clean the canvas by using canvas.drawColor(Color.BLACK), but that didn't help either. I already tried to use background colors instead of a background image which changes randomly every tick, but it didn't change but stays always the same.
I figured out that the canvas at the very first call has a density of (for example) 240. After the second tick, the canvas density is always 0. I know that the density will not help me here, but maybe it's an important information for someone.
Here are the important classes....
game layout, R.layout.game
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gameContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mydomain.mygame.base.game.GameSurface
android:id="#+id/gameSurface"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:background="#drawable/background_game" >
</com.mydomain.mygame.base.game.GameSurface>
<!-- ...more definitions -->
</LinearLayout>
GameActivity (contains layout)
public class GameActivity extends Activity
{
#SuppressWarnings("unused")
private GameSurface gameSurface;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
gameSurface = (GameSurface)findViewById(R.id.gameSurface);
//TODO on button click -> execute methods
}
}
GameSurface (log in onDraw shows updated coordinates every tick)
public class GameSurface extends SurfaceView implements SurfaceHolder.Callback
{
private GameThread thread;
protected final static int TICK_FREQUENCY = 100;// ms, stays always the same. It's a technical constant which doesn't change
private static final String TAG = GameSurface.class.getSimpleName();
public GameSurface(Context context, AttributeSet attrs)
{
super(context, attrs);
ShapeManager.INSTANCE.init(context);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
setFocusable(true); // make sure we get key events
thread = new GameThread(holder, this);
}
public void updateStatus()
{
GameProcessor.INSTANCE.updateShapes();
}
#Override
protected void onDraw(Canvas canvas)
{
for (Shape shape : GameProcessor.INSTANCE.getShapes())
{
Log.i(TAG, "getX()=" + shape.getX() + ", getY()=" + shape.getY());
canvas.drawBitmap(shape.getBitmap(), shape.getX(), shape.getY(), null);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
//will never invoked since we only operate in landscape
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
// start the thread here so we don't busy-wait in run
thread.setRunning(true);
new Thread(thread).start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.i(TAG, "executing surfaceDestroyed()...");
thread.setRunning(false);
}
}
GameThread
public class GameThread implements Runnable
{
private SurfaceHolder surfaceHolder;
private boolean running = false;
private GameSurface gameSurface;
private long lastTick;
public GameThread(SurfaceHolder surfaceHolder, GameSurface gameSurface)
{
this.surfaceHolder = surfaceHolder;
this.gameSurface = gameSurface;
lastTick = System.currentTimeMillis();
}
#Override
public void run()
{
Canvas canvas;
while (running)
{
canvas = null;
if (System.currentTimeMillis() > lastTick + GameSurface.TICK_FREQUENCY)
{
long timeDifference = System.currentTimeMillis() - (lastTick + GameSurface.TICK_FREQUENCY);
try
{
canvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder)
{
gameSurface.updateStatus();
gameSurface.draw(canvas);
}
}
finally
{
if (canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
lastTick = System.currentTimeMillis() - timeDifference;
}
}
}
public void setRunning(boolean running)
{
this.running = running;
}
}
Any ideas why this code doesn't update my canvas? I can't explain it. I do not post ShapeManager and GameProcessor since they don't have anything to do with the problem (and they only load and control the current states and speed of the game).
[UPDATE]
I figured out that onDraw() is invoked before the game thread has started. That means that canvas is passed to this method before thread is using it. The interesting thing is that, after the thread has started, it always uses the same canvas, but it's not the canvas reference which is passed the very first time. Although canvas = surfaceHolder.lockCanvas(null); is assigned every tick, it's always the same reference, but it's not the original reference.
In a working example of mine, the reference is always the same, since I create the bitmaps at constructor initialization time. I can't do that in my current implementation, since I have to do calculations with values I get from onMeasure() which is invoked much later than the constructor.
I tried to somehow pass the original canvas to the thread, but the reference still changes. Meanwhile I think this is the problem, but I don't know how to solve it yet.
As often happens, I found the solution on my own.
Obviously it's really a problem that it draws to different canvas instances. I'm still not sure why this happens. Didn't have the problem before. Nevertheless, I can avoid drawing to canvas by setting setWillNotDraw(true); in my GameSurface constructor and I must not invoke gameSurface.draw(canvas) in my thread, but gameSurface.postInvalidate() instead.
I have 2 virtually identical textviews in a layout that are updated by 2 similar bits of code. When the app runs (whether emulator or phone) one is updated but the other is not - but when run the same way in debug mode they are both updated. I've done lots of searching online, read lots of questions and answers and have tried various ways to update the textview, but the weird thing is this combination: it works in debug but not live, but another texview and a canvas are updated ok. Even a log message (placed in the same if clause as this textview update) works in debug but not when run on emulator (other log messages are being
displayed ok).
The layout also has a canvas used for a simple game and the relevant code is within the running of that game. The canvas is updated by a repeating runnable. I wanted to add a time limit to the game so thought I'd simply mark the start time and then check in the runnable the time since the start. The textview is intended to show the seconds passing - and it works in debug! Abbreviated version of code below.
Maybe it's something about timing, something not having time to run properly? It doesn't need another runnable, does it, seeing as it's managing to update the other textview ok? Should you do runnables within runnables?
Any help or guidance appreciated.
Layout
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/trees2"
android:orientation="vertical"
tools:context=".GameActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="#+id/score"
android:layout_width="54dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical|center_horizontal"
android:text="0"
android:background="#drawable/border"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
<TextView
android:id="#+id/countdown"
android:layout_width="54dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical|center_horizontal"
android:text="0"
android:background="#drawable/border"
android:textAppearance="?android:attr/textAppearanceLarge" >
</TextView>
</LinearLayout>
<TextView
android:id="#+id/the_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="" />
<couk.jit.drawing.GameBoard
android:id="#+id/the_canvas"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="20dip" />
</LinearLayout>
GameBoard.java
public class GameBoard extends View {
public GameBoard(Context context, AttributeSet aSet) {
super(context, aSet);
p = new Paint();
sprite1 = new Point(-1,-1);
m = new Matrix();
bm1 = BitmapFactory.decodeResource(getResources(), R.drawable.b1);
sprite1Bounds = new Rect(0,0, bm1.getWidth(), bm1.getHeight());
bm = BitmapFactory.decodeResource(getResources(),R.drawable.go_sign);
}
synchronized public boolean didItHitTarget() {
if .... return true;
else ... return false;
}
#Override
synchronized public void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), p);
canvas.drawBitmap(bm3, sprite3.x, sprite3.y, null);
}
}
GameActivity.java
public class GameActivity extends Activity implements OnTouchListener {
private static final int FRAME_RATE = 20;
long startTime;
int timerCount = 0;
int score = 0;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
h.postDelayed(new Runnable() {
#Override
public void run() {
initGfx();
}
}, 1000);
}
synchronized public void initGfx() {
Point p1, p2;
p1 = getStartPoint();
((GameBoard)findViewById(R.id.the_canvas)).setSprite1(p1.x, p1.y);
((View)findViewById(R.id.the_canvas)).setOnTouchListener(this);
frame.removeCallbacks(frameUpdate);
frame.postDelayed(frameUpdate, FRAME_RATE);
}
private Runnable frameUpdate = new Runnable() {
#Override
synchronized public void run() {
if (state == GameState.Ready)
updateReady();
if (state == GameState.Running)
updateRunning();
}
synchronized public void updateReady() {
frame.removeCallbacks(frameUpdate);
((GameBoard)findViewById(R.id.the_canvas)).invalidate();
startTime = System.nanoTime(); //set game start time
frame.postDelayed(frameUpdate, FRAME_RATE);
}
synchronized public void updateRunning() {
frame.removeCallbacks(frameUpdate);
if (((GameBoard)findViewById(R.id.the_canvas)).didItHitTarget()) {
score = score + 1;
//This works fine
((TextView)findViewById(R.id.score)).setText(Integer.toString(score));
Point p1;
p1 = getStartPoint();
((GameBoard)findViewById(R.id.the_canvas)).setSprite1(p1.x, p1.y);
}
float deltaTime = (System.nanoTime() - startTime) / 100000000000.0f;
int j = (int) deltaTime;
if ((int)deltaTime > timerCount) {
timerCount = timerCount + 1;
//This works in debug but does not update live
((TextView)findViewById(R.id.countdown)).setText(Integer.toString(timerCount));
Log.i(TAG, "Updating countdown");
}
((GameBoard)findViewById(R.id.the_canvas)).invalidate();
frame.postDelayed(frameUpdate, FRAME_RATE);
}
};
This was my solution in case anyone interested (or can still suggest better way!).
Going from blackbelt's point that certain parts of the code are simply not being entered, I thought that, although I couldn't find the reason, it must be something to do with the complexity of the timer clock combined with android's thread handling. So I created the timer using a separate thread, as in code here:
Android update TextView in Thread and Runnable
I want to show 2 images (one when connected and the second when disconnected) and i'm using a handler to handle that, however, i'm not having any of the 2 images showen, don't know why :.
private Runnable handleUpdateStatus = new Runnable()
{
Boolean mRegistered;
public void run()
{
ImageView statusImageDisplay = (ImageView)findViewById(R.id.connected);
if (mRegistered)
{
statusImageDisplay.setImageDrawable(getResources().getDrawable(R.drawable.connected));
Log.i("CONNECTED","IMAGE SET");
}
else
{
statusImageDisplay.setImageDrawable(getResources().getDrawable(R.drawable.disconnected));
Log.i("DISCONNECTED","IMAGE SET");
}
}
};
Changing image code excerpt:
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Enregistré au serveur.");
Log.d("SUCCEED","Registration DONE");
mRegistered = true;
mRegistrationUpdateHandler.removeCallbacks(handleUpdateStatus);
mRegistrationUpdateHandler.postDelayed(handleUpdateStatus, 4000);
}
What to do when the registration failed? this code:
public void onRegistrationFailed(String localProfileUri, int errorCode,String errorMessage) {
updateStatus("Enregistrement échoué. Veuillez vérifier vos paramètres.");
Log.d("ERROR REGISTRATION",errorMessage);
mRegistered = false;
mRegistrationUpdateHandler.removeCallbacks(handleUpdateStatus);
mRegistrationUpdateHandler.postDelayed(handleUpdateStatus, 2000);
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/sipLabel"
android:textSize="20sp"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ImageView android:id="#+id/connected" android:src="#drawable/connected"
android:layout_below="#id/sipLabel"
android:layout_width="fill_parent" android:scaleType="center"
android:layout_height="fill_parent" android:layout_weight="0.35"
android:gravity="center" android:visibility="invisible" />
</LinearLayout>
Any idea please of how solving this problem ?
Thank you very much.
You (must) have your mRegistered variable declared twice, and while you're setting the value for the global one (the one declared inside your Activity), you examine the value of the other one, declared inside your handleUpdateStatus Runnable.
You should clean up your code a bit:
remove the mRegistration declaration
from your Runnable implementation,
// Boolean mRegistered;
set the image drawable via resource
id,
and it will work:
private boolean mRegistered;
private Runnable handleUpdateStatus = new Runnable()
{
public void run()
{
ImageView statusImageDisplay = (ImageView) findViewById(R.id.connected);
if (mRegistered)
{
statusImageDisplay.setImageResource(R.drawable.connected);
Log.i("CONNECTED", "IMAGE SET");
}
else
{
statusImageDisplay.setImageResource(R.drawable.disconnected);
Log.i("DISCONNECTED", "IMAGE SET");
}
}
};
This is all you need to change (assuming, that your layout really contains an image with id connected).
Update
As about mRegistrationUpdateHandler, you should declare it as a global variable of your Activity (either final or initialized inside the onCreate method):
private final Handler mRegistrationUpdateHandler = new Handler();
or
private Handler mRegistrationUpdateHandler;
I'm trying to have my Activity update an ImageView whenever a boolean value changes in another class.
Therefore i have some sort of timer that starts on my first onCreate()
private void startTimer() {
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 2000); // first run after 2 secs
}
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
connectionControl.checkNetworkState();
System.out.println("online?: " + connectionControl.isOnline());
mHandler.postDelayed(this, 15000); // repeat every x/1000 secs
}
};
My class ConnectionControl has a boolean, that gets set to either true or false whether my app can reach a specific http-host.
Now my question is: how can i achieve a automatic change on the ImageView in my Activity to display the boolean's value?
I already looked at Observer-Pattern, EventListener, BroadcastReciever but I'm stuck at finding the right solution.
Also, i want to use the listening in other Activities.
What has worked so far was starting/stopping the timer-thing for each activity and have the ImageView update inside the run() method. But my guess is, there has to be a way around the redundancy.
I think you are in search of AsyncTask , by using it you can made a call to webservice asynchronously and after the successful call to the webservice, we can process the fetched data.
Just go through this article: http://developer.android.com/resources/articles/painless-threading.html.
I think you needs this: (from android.com)
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
For more info about AsyncTask , here is link: http://developer.android.com/reference/android/os/AsyncTask.html
Here is how I did it.
I made a layout file for the custom titlebar thing, that has an ImageView.
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<ImageView android:id="#+id/title_statusimg"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:src="#drawable/connected" android:layout_centerVertical="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
</merge>
I include this in every activities layout file i want to use it.
<include layout="#layout/titlebar" />
Also, i made a StatusActivity that extends Activity. It receives a Broadcast that is send from whenever an background thread detects a change in the connectivity to the webserver.
public class StatusActivity extends Activity {
private String CONNECTION_STATUS = "app.CONNECTION_STATUS";
private ImageView conn;
#Override
protected void onResume() {
super.onResume();
IntentFilter iFilter = new IntentFilter(CONNECTION_STATUS);
registerReceiver(mBroadcastReceiver, iFilter);
conn = (ImageView) findViewById(R.id.title_statusimg);
if (ConnectionControl.isOnline()) {
conn.setImageResource(R.drawable.connected);
} else {
conn.setImageResource(R.drawable.nconnected);
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mBroadcastReceiver);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectionControl.isOnline()) {
conn.setImageResource(R.drawable.connected);
} else {
conn.setImageResource(R.drawable.nconnected);
}
}
};
}
Every Activity that shall use this Status-Image extends StatusActivity instead of Activity.
Hope i covered everything, atleast for me it's working.