Android - Change the Image View Source at run time after few seconds - android

The following code is for a splash screen in my app.What I need to be done is when the activity loads the image should be displayed as default and then after few seconds the image should be changed to another in the same activity. I have another image like the first one with different color. I wanted to change the screen for that image after few seconds.
I have done it like this in my code.
package com.ruchira.busguru;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class SplashScreen extends Activity {
ImageView imgBus;
MediaPlayer introSound, bellSound;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
imgBus = (ImageView) findViewById(R.id.imgBus);
imgBus.setImageResource(R.drawable.blackbus);
introSound = MediaPlayer.create(SplashScreen.this, R.raw.enginestart);
introSound.start();
Thread timer = new Thread(){
public void run(){
try{
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
imgBus.setImageResource(R.drawable.bluekbus);
}
}
};
timer.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.splash_screen, menu);
return true;
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
introSound.stop();
finish();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
introSound.stop();
finish();
}
}
but the problem is the program stops by executing in the thread saying...
"android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
How I can achieve this target ? Does anybody please help me to sort out this problem. I am new to android development..
Thanks.

You should use the ImageView's Handler and a Runnable. Handler's are schedulers specific to Android and they can run on the UI thread. Try this:
ImageView imgBus;
MediaPlayer introSound, bellSound;
Runnable swapImage = new Runnable() {
#Override
public void run() {
imgBus.setImageResource(R.drawable.bluekbus);
}
};
And inside onCreate() call:
imgBus = (ImageView) findViewById(R.id.imgBus);
imgBus.setImageResource(R.drawable.blackbus);
imgBus.postDelayed(swapImage, 3000); // Add me!
Understand that splash screens are frowned upon because you should focus on starting the app as soon as possible (while loading the slower element in the background). However sometimes a slight delay is unavoidable.

Write this inside finally
runOnUiThread(new Runnable() {
public void run() {
SplashScreen.class.img.setImageResource(R.drawable.bluekbus);
}
});
You should always update your UI from the UI Thread itself...

Try the following,
We cannot access and update the UI from worker threads, only we can access the UI from UIThread. If we need it to update with background thread then we can use Handler to do this like in the following code.
this.imgBus = (ImageView) findViewById(R.id.splashImageView);
imgBus.setImageResource(R.drawable.your_first_image);
this.handler = new Handler();
introSound = MediaPlayer.create(SplashTestForSO.this, R.raw.enginestart);
introSound.start();
Thread timer = new Thread(){
public void run(){
try{
sleep(2000);
YourActivity.this.handler.post(runnable);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
}
}
};
timer.start();
this.runnable = new Runnable() {
public void run() {
//call the activity method that updates the UI
YourActivity.this.imgBus.setImageResource(R.drawable.your_scond_image_view);
}
};

Related

Unable to update the UI using the message from the handler

Hello everyone, I am new to android application development. I have written and code and trying to update the UI from the message obtained from handler. I have tried to debug the code but i couldn't find what the error is. please help me out. Thank you.
package com.threadcommunicationexample;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
Button Click;
TextView Message;
Handler Mrmessenger;
int Counter = 0;
/*
*Initialisation area....
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Click = (Button) findViewById(R.id.ClickButton);
Message = (Button) findViewById(R.id.TextView);
Click.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Operation to be performed after the button click
Runnable myThreadRunner = new Runnable() {
#Override
public void run() {
// Saving the text in bundle and passing it to handler ....
while (Counter < 100) {
try {
Thread.sleep(100);
Message msg = Mrmessenger.obtainMessage();
Bundle myBundle = new Bundle();
myBundle.putString("Communication", "Loading....");
msg.setData(myBundle);
//Sending the bundle to Handler
Mrmessenger.sendMessage(msg);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Mrmessenger = new Handler() {
public void handleMessage(final Message msg) {
Mrmessenger.post(new Runnable() {
// Getting the message from the handler and updating it using textview
#Override
public void run() {
Bundle ComBundle = msg.getData();
// TODO Auto-generated method stub
String myMessage = ComBundle
.getString("Communication");
Message.setText(myMessage);
}
});
}
};
Counter++;
}
}
};
Thread myRunner = new Thread(myThreadRunner);
//creating a thread and passing the runnable object.
myRunner.start();
}
}
For one thing, the line
Message msg = Mrmessenger.obtainMessage();
will fail since you don't initialize Mrmessenger until a few lines later.
Would recommend you use AsyncTask for this type of thing; it deals with all of the threading so you don't have to.
Also: per Java conventions, variable names should start with a lowercase letter, class names start with an uppercase letter. This would make your code easier for others to read.
the problem with your code is, that the run method in your handler is called on another thread than the main / ui thread.
To make the code working you can use the following code..
runOnUiThread(new Runnable() {
public void run() {
Message.setText(myMessage);
}
});
..to run the ui update explicitly on the ui thread.

Text view doesn't show any text

I am new to java and andriod and i think that i did something wrong with thread
Program starts without any errors.
I have inserted one button just for test and it shows without problem. Text view doesnt even displays "Hello world" default string.
Here is the code
package com.example.studentservis;
import android.R.string;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.w3c.dom.Text;
public class MainActivity extends Activity {
StringHandler stringHandler = new StringHandler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread.run();
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
}
#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;
}
Thread thread = new Thread(){
public void run(){
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
// TODO Auto-generated catch block
stringHandler.setString(e.getMessage());
}
}
};
public String webRequest() throws Exception{
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
return jobNode.get(0).text();
}
public class StringHandler
{
public String str = "test";
public void setString(String s)
{
str = s;
}
public String getString()
{
return str;
}
}
}
When you start a new Thread, the UI thread won't wait until the new thread is complete. That is the purpose of the Threads.
Here :
thread.run();
When you a start the new thread to update the stringHandler, the UI thread tries to process the next command which is :
txtView.setText(stringHandler.getString());
When the UI thread gets to this, the stringHandler hasn't updated yet, so It's null and thus it will show nothing in the textview.
All you should do is to try to update the textview from the new Thread when it's finished.
Try this:
Thread thread = new Thread(){
public void run(){
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
// TODO Auto-generated catch block
stringHandler.setString(e.getMessage());
}
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
}
});
}
};
You can use a handler or a asyctask for this purpose. Asynctask is easier.
http://developer.android.com/reference/android/os/AsyncTask.html
You can create your own thread but remember to update ui on the ui thread.
activity_main.xml
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="166dp"
android:text="Loading..." />
</RelativeLayout>
MainActivity.java
Removed StringHandler cause i felt it was unnecessary in this context.
public class MainActivity extends Activity {
TextView txtView ;
String s;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = (TextView)this.findViewById(R.id.textView1); // initialize textview
//txtView.setText(stringHandler.getString());
new Thread(new Runnable() { // thread
#Override
public void run(){
try {
s = webRequest(); // get string
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
runOnUiThread(new Runnable() //run on ui threa
{
public void run()
{
txtView.setText(s); // update ui on the ui thread.
}
});
}
}).start();
}
public String webRequest() throws Exception{ // web request
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
return jobNode.get(0).text();
}
}
Resulting snap shot
This part of your code : txtView.setText(stringHandler.getString());
should be put after the thread finished.
thread.run(); <------ Start running thread in background
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
// the textView was set without knowing whether the Thread is finished or not.
// thus, textView is shown as empty, because stringHandler.getString() still has empty string
My suggestion is that you implement it inside an asyncTask, so that you can set the text within onPostExecute()
Good luck ^^
EDIT :
here's some example AsyncTask
private class StringSet extends AsyncTask <Void,Void,Void> {
#Override
protected void doInBackground(Void... params) {
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
stringHandler.setString(e.getMessage());
}
}
#Override
protected void onPostExecute(Void... results) {
txtView.setText(stringHandler.getString());
}
}
And replace your thread.run() with new StringSet().execute();

Main Activity not opening

My app seems to start up properly, with the splash screen and stuff. But when it sleeps for 6 secs and when it supposed to get into the main activity the app crashes any help please?
Here is me code (android.intent.action1.MAINACTIVIVTY, the "action" was purposely changed to "action1")
package com.hellhogone.multitools;
import com.hellhogone.multitools.R;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Window;
import android.view.WindowManager;
public class Splash extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.splash);
MediaPlayer yo = MediaPlayer.create(Splash.this, R.raw.smusic);
yo.start();
Thread timer = new Thread(){
public void run(){
try{
sleep(6000);
}catch(InterruptedException e){
e.printStackTrace();
}finally{
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
You cannot start an activity from another thread than the UI thread. To avoid this problem you can use runOnUiThread() :
}finally{
runOnUiThread(new Runnable() {
public void run() {
Intent h1 = new Intent("android.intent.action1.MAINACTIVITY");
startActivity(h1);
}
});
}

android threads unclear

I have this code:
package org.example.Threading;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ThreadingActivity extends Activity implements OnClickListener {
/** Called when the activity is first created. */
private doinback background = new doinback();
Handler handle= new Handler(){
#Override
public void handleMessage(Message msg) {
Log.e("INSIDE HANDLER", "About to stop the thread.");
background.stopThread();
}};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.e("ONCREATE", "BEFORE Thread");
background.start();
Log.e("ONCREATE", "AFTER Thread started");
View button = (Button)findViewById(R.id.button1);
button.setOnClickListener(this);
}
class doinback extends Thread{
private volatile boolean isRunning = false;
public void run() {
while(isRunning){
Log.e("INSIDE THREAD", "about to sleep");
handle.sendMessage(handle.obtainMessage());
}
}
public void stopThread()
{
isRunning = false;
}
public void startThread(){
Log.e("INSIDE StartThread","MAKING isRunning True");
isRunning = true;
}
}
public void onClick(View v) {
background.startThread();
Log.e("INSIDE ONCLICK", "made isRunning true, about to leave");
}
}
I am trying to understand why it does not go back to the thread and if there is something I am doing wrong and if so what is the best way to go back and forth from a thread, for instance with the stopThread() function I change the value of the while variable to stop the thread from running. When I run the code and press the button it does not start the thread. Any ideas why?
When background.start() is called, isRunning is still false, so the thread is started(but didn't enter the while loop) and stopped immediately.
To ensure the thread to enter the while loop when startThread is called, you can put the following code in the startThread() method:
public void startThread(){
isRunning = true;
start();
}
And you don't call background.start() in onCreate(), just remove that line.
EDIT
If you want to keep a single thread alive, so you can "start" it and "stop" it as many times as you like, you can use the following code:
public void run () {
while (isRunning) {
if(!isWorking) {
try { Thread.sleep(10); } catch (InterruptedException ex) { }
continue;
}
//.. do your work here.
}
}
You control the running state of the thread with isRunning, and the working state with isWorking.

cant call function from inside thread or asyntask

I am using a thread and a handler in android. The app works fine as long as i dont any function from outside the activity. But if i call some funcyion from outside the activity from inside a thread, it gives NullPointerException.
package com.prog;
import com.API.TextBoxCheck;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class ProgressBarExample extends Activity {
private Handler handler = new Handler();
int i;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn=(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
TextView tv=(TextView)findViewById(R.id.textView1);
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Thread thread = new Thread(null, doBackgroundThreadProcessing,
"Background");
thread.start();
}});
Button stopBtn=(Button)findViewById(R.id.button2);
stopBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}});
}
private Runnable doBackgroundThreadProcessing = new Runnable() {
public void run() {
try {
backgroundThreadProcessing();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private void backgroundThreadProcessing() throws InterruptedException {
TextView tv=(TextView)findViewById(R.id.textView1);
i=0;
while(i<100)
{
handler.post(doUpdateGUI);
Thread.sleep(50);
i++;
}
EditText et=(EditText)findViewById(R.id.editText1);
TextBoxCheck tbc = new com.API.TextBoxCheck();
String reply=tbc.TextBoxChecker(et.getText().toString(),10);
Log.d("thread", reply);
}
private Runnable doUpdateGUI = new Runnable() {
public void run() {
updateGUI();
}
private void updateGUI() {
// TODO Auto-generated method stub
TextView tv=(TextView)findViewById(R.id.textView1);
tv.setText(i+"%");
}
};
}
I have left out the code of textBoxCheck becoz i think it may be unnecesarry here.
Please help me on this.
PS. : I also tried using AsyncTask but the same problem occurs.
You are not on UI thread. You must be on UI thread to operate on any UI items. Create a handler on the UI thread and call your backgroundThreadProcessing(); from the handler and not from a non-UI thread.

Categories

Resources