i am trying to implement Runnable and run the Run() method when a thread is started. but when i run the program it crashed.
MainActivity
public class MainActivity extends Activity implements Runnable{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread t1;
t1=new Thread(this);
t1.start();
}
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
i tried changing it to t1=new Thread(new MainActivity());(app crashed) or just t1=new Thread(); never crash but no output.
how do i implement a Runnable Run when a thread is started? i search all over the place but could not find an answer. i need to include this function in my main project code too. but i create a separate testing project just to get how this works so i can add it in my main project code myself. at my main project it crashed at this point too. it never reached the Run method.
after it crashed, this is the LogCat
01-21 13:03:06.460: W/dalvikvm(879): threadid=11: thread exiting with uncaught exception (group=0xb3a6fb90)
01-21 13:03:06.460: E/AndroidRuntime(879): FATAL EXCEPTION: Thread-51
01-21 13:03:06.460: E/AndroidRuntime(879): Process: com.example.testthreadrun, PID: 879
01-21 13:03:06.460: E/AndroidRuntime(879): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-21 13:03:06.460: E/AndroidRuntime(879): at android.os.Handler.<init>(Handler.java:200)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.os.Handler.<init>(Handler.java:114)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast$TN.<init>(Toast.java:327)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast.<init>(Toast.java:92)
01-21 13:03:06.460: E/AndroidRuntime(879): at android.widget.Toast.makeText(Toast.java:241)
01-21 13:03:06.460: E/AndroidRuntime(879): at com.example.testthreadrun.MainActivity.run(MainActivity.java:29)
01-21 13:03:06.460: E/AndroidRuntime(879): at java.lang.Thread.run(Thread.java:841)
01-21 13:03:07.010: I/Choreographer(879): Skipped 126 frames! The application may be doing too much work on its main thread.
01-21 13:03:07.970: I/Choreographer(879): Skipped 165 frames! The application may be doing too much work on its main thread.
01-21 13:03:08.840: D/gralloc_goldfish(879): Emulator without GPU emulation detected.
01-21 13:03:10.770: I/Choreographer(879): Skipped 31 frames! The application may be doing too much work on its main thread.
01-21 13:03:26.670: I/Process(879): Sending signal. PID: 879 SIG: 9
Since you are trying to update the UI, you need to do it on the UI Thread. You should use something like runOnUiThread() or AsyncTask.
runOnUiThread(new Runnable()
{
#Override
public void run()
{
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
});
or
Example of AsyncTask
AsyncTask Docs
You can't update ui from a background thread. You can update ui from ui thread only.
You can use runOnUiThread. But to just display a toast why do you require a thread?.
http://developer.android.com/guide/components/processes-and-threads.html
You cannot do UI changes (like a toast) on a thread that is not the UI thread. Use this instead:
public void run() {
MainActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show();
}
});
}
However, why are you creating a whole separate thread to show a toast? You're better off just putting Toast.makeText(MainActivity.this, "display something",
Toast.LENGTH_LONG).show(); in your onCreate method.
Related
I keep getting this error message when i run my game:
01-21 16:14:00.911: E/AndroidRuntime(15779): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6373)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:878)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.ScrollView.requestLayout(ScrollView.java:1483)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.view.View.requestLayout(View.java:17566)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.checkForRelayout(TextView.java:6914)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:4096)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:3954)
01-21 16:14:00.911: E/AndroidRuntime(15779): at android.widget.TextView.setText(TextView.java:3929)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.Game.Overview_Viewupdate(Game.java:305)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.Game.tick(Game.java:174)
01-21 16:14:00.911: E/AndroidRuntime(15779): at com.gamerscave.corpboss.game.GameThread.run(GameThread.java:27)
this error code is caused by:
public void Overview_Viewupdate(){
tv1.setText("Balance: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, bal));
tv2.setText("Income: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, inc));
tv3.setText("Nett worth: " + Maths.coustomFormat(DEFAULT_BIG_NUMBER_PATTERN, NettWorth));
tv4.setText("Shares: " + sharePercent + "%");
tv5.setText("Share value: " + ShareVal);
tv6.setText("Date: " + Date);
}
and it is called at:
public void tick(){
player.tick();
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>1000)
{
nextDay(day, year, month);
System.out.println("New day: " + day);
startTime = System.nanoTime();
}
if(view1){
Overview_Viewupdate();
}
}
for some reason it isnt triggered on the launch. the launch change is called in the init method. the init method is called from the GameThread-class' run method. So how do I avoid this error and still have a game thread that works?
The error above happens because Android doesn’t want other threads, such as your timer, messing with its GUI. So, what you need to do is politely ask Android to make the update for you.
public void tick(){
player.tick();
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>1000)
{
nextDay(day, year, month);
System.out.println("New day: " + day);
startTime = System.nanoTime();
}
if(view1){
runOnUiThread(new Runnable() {
public void run(){
Overview_Viewupdate();
}
});
}
}
Your problem is that you are updating UI elements on a non-UI thread. There's a couple of ways around this. In your case, I believe the best way is to use a RunOnUiThread statement, as follows (Note, this has to be done on an Activity):
RuOnUiThread(new Runnable() {
void run() {
Overview_Viewupdate();
}
});
Your problem is that you are updating UI elements on a non-UI thread. There's a couple of ways around this. In your case, I believe the best way is to use a RunOnUiThread statement, as follows (Note, this has to be done on an Activity):
RuOnUiThread(new Runnable() {
void run() {
Overview_Viewupdate();
}
});
This code would replace your current calling of Overview_ViewUpdate. Alternatively, you could consider an AysncTask, where your OnPostExecute runs Overview_ViewUpdate() and your doInBackground() does the operations that must be run in the background.
Also, make sure your UI elements are created on the UI thread. This is usually done in OnCreate or OnStart. AddContentView(...) or SetContentView(...) counts as such.
I am new here to Android. My application is crashing with errors after sleep runs (5000) and then my toast is not showing in my finally block. What is causing these errors in my code?
public class LoginActivity extends ActionBarActivity {
TextView textview;
Toast toast;
#Override
protected void onCreate(Bundle ThisisLoginActivity) {
super.onCreate(ThisisLoginActivity);
setContentView(R.layout.activity_login);
textview = (TextView) findViewById(R.id.textView1);
Thread thread = new Thread() {
public void run() {
try{
sleep(5000);
} catch(InterruptedException e) {
e.printStackTrace();
}
finally {
toast = Toast.makeText(getApplicationContext(), "Sleep Runing", Toast.LENGTH_SHORT);
toast.show();
}
}
};
thread.start();
}
}
Here is my LogCat:
01-08 22:30:32.782: E/Trace(3503): error opening trace file: No such file or directory (2)
01-08 22:30:33.322: I/Choreographer(3503): Skipped 47 frames! The application may be doing too much work on its main thread.
01-08 22:30:33.402: D/gralloc_goldfish(3503): Emulator without GPU emulation detected.
01-08 22:30:33.531: I/Choreographer(3503): Skipped 62 frames! The application may be doing too much work on its main thread.
01-08 22:30:39.122: I/Choreographer(3503): Skipped 31 frames! The application may be doing too much work on its main thread.
01-08 22:30:39.272: I/Choreographer(3503): Skipped 43 frames! The application may be doing too much work on its main thread.
01-08 22:30:45.772: W/dalvikvm(3503): threadid=11: thread exiting with uncaught exception (group=0x40a71930)
01-08 22:30:45.792: E/AndroidRuntime(3503): FATAL EXCEPTION: Thread-153
01-08 22:30:45.792: E/AndroidRuntime(3503): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-08 22:30:45.792: E/AndroidRuntime(3503): at android.os.Handler.<init>(Handler.java:197)
01-08 22:30:45.792: E/AndroidRuntime(3503): at android.os.Handler.<init>(Handler.java:111)
01-08 22:30:45.792: E/AndroidRuntime(3503): at android.widget.Toast$TN.<init>(Toast.java:324)
01-08 22:30:45.792: E/AndroidRuntime(3503): at android.widget.Toast.<init>(Toast.java:91)
01-08 22:30:45.792: E/AndroidRuntime(3503): at android.widget.Toast.makeText(Toast.java:238)
01-08 22:30:45.792: E/AndroidRuntime(3503): at com.example.incrementdecrement.LoginActivity$1.run(LoginActivity.java:48)
01-08 22:30:46.462: I/Choreographer(3503): Skipped 34 frames! The application may be doing too much work on its main thread.
You cannot directly manipulate the user interface from another thread. The main thread is responsible for all UI changes.
For a solution to a similiar problem see: Android: Toast in a thread
Just use Activity's runOnUiThread method from your thread:
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(LoginActivity.this, "Sleep Runing", Toast.LENGTH_SHORT).show();
}
});
Method in onCreate :
private void toastPublic(final String message){
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
Toast.makeText(getBaseContext(),""+message,
4 /*Toast.LENGTH_SHORT*/).show();
}});
}
Next : use in inside Thread
So I have an app that uses a surface view that runs a separate thread for the UI. It was taken almost directly from the Lunar Landing sample app. The app also uses Bluetooth service on another thread but I am sure that this is not related to the problem because I can disable bluetooth all together and it still happens.
The problem in my app is that the app when closed and then reopened does not start running the UI thread afterthread.start() except it throws an error. In the Lunar example they have thread.start() in the onSurfaceCreated method. The problem is when I restart my app (it calls onPause then onSurfaceDestroy) the thread is already running and I get an error when I try to start it. My code for onSurfaceCreated, onPause, onResume and onSurfaceDestroyed is all the same as the example. I know I can use if (this.getState() == Thread.State.NEW) { but that seems like it will mask some of my other issues. I want to master the activity life cycle.
My question is how does the Lunar Lander stop the thread? And why is mine not stopping with the same code and running at the onSurfaceCreated method. Obviously I am missing something. As far as I know in the Lunar example the only thing that is called on the thread on a destroy is thread.join().
Edit 3: Here is the Lunar Lander Example Code if needed.
So these are the three override methods in my surfaceview...
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceCreated");
// start the bluetooth service
thread.startBluetoothService();
// start the game
//if (this.getState() == Thread.State.NEW) {
Log.d(TAG, "thread start");
// start running the thread
this.start();
//}
Log.d(TAG, "running to true");
// release the thread lock
setRunning(true);
}
// surfaceChanged is called at least once after surfaceCreated
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d(TAG, "surfaceChanged");
// reset the surface size
thread.setSurfaceSize(width, height);
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d(TAG, "surfaceDestroyed");
// make sure to shut down the thread cleanly
boolean retry = true;
// stop the running thread
thread.setRunning(false);
// continuously try to shut down the thread
while (retry){
try{
// blocks calling thread until termination
thread.join();
// stop the bluetooth service
//thread.stopBluetoothService();
retry = false;
}catch(InterruptedException e){
//try to shut it down again
}
}
}
I am really pretty lost with all of this. Any help would be very appreciated, thanks!
Edit:
So I did a little more testing. When the user hits home(which exits the app completely) onPause, then onSurfaceDestroy like I said before. Then when it restarts I get onResume followed by onSurfaceCreated. I think my issue is that it is not calling onCreate when you reenter the app.
Some more questions...
What distinguishes the difference between a onPause and a onDestroy? I think my problem is that since onCreate is not being called I don't have a newly created UI thread which seems like it is still running.
Should the thread be stopped even on a onPause? Because then I am not garenteed to run onCreate which re instantiates the thread. Here is the onCreate code...
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wobble);
// get view and thread
wobbleView = (WobbleView) findViewById(R.id.wobble);
wobbleThread = wobbleView.getThread();
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
// alert the user of bluetooth failure
Toast.makeText(this, "Bluetooth is not available, using internal devices sensors", Toast.LENGTH_LONG).show();
// set the data source to internal sensors - so we'll just use the devices accel
wobbleThread.setDataSource(WobbleThread.INTERNAL_SENSORS);
// bluetooth is supported so make sure its enabled and
}else{
// make sure bluetooth is enabled on the device
if (!mBluetoothAdapter.isEnabled()) {
Log.d(TAG, "starting request to enable bluetooth");
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// all is well with bluetooth - use bluetooth
Log.d(TAG, "setting bluetooth to bluetooth");
wobbleThread.setDataSource(WobbleThread.BLUETOOTH);
}
// give the LunarView a handle to the TextView used for messages
wobbleView.setTextView(
(TextView) findViewById(R.id.text_accel),
(TextView) findViewById(R.id.game_msg),
(TextView) findViewById(R.id.text_score),
(TextView) findViewById(R.id.bluetooth_status)
);
if (savedInstanceState == null) {
// we were just launched: set up a new game
//wobbleThread.setState(wobbleThread.STATE_READY);
} else {
//wobbleThread.setRunning(true);
// we are being restored: resume a previous game
//wobbleThread.restoreState(savedInstanceState);
}
}
Edit 2:
Some logcat output
So this is what I get when the thread.start() is called after reopening the app.
11-18 22:50:44.104 4868-4868/com.bme.shawn.wobble E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalThreadStateException: Thread already started
at java.lang.Thread.checkNotStarted(Thread.java:871)
at java.lang.Thread.start(Thread.java:1025)
at com.bme.shawn.wobble.WobbleThread.startGame(WobbleThread.java:213)
at com.bme.shawn.wobble.WobbleView.surfaceCreated(WobbleView.java:94)
at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:240)
at android.view.View.dispatchWindowVisibilityChanged(View.java:7903)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1071)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1289)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1050)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5750)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at android.view.Choreographer.doFrame(Choreographer.java:561)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5406)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
And if I use the thread.getState check and bypass the error I get this when I close then reopen the app. (logs in basically everything) In this case when the app reopens the thread is not drawing at all. Which is very weird since without the check I get an error saying that the thread is already running.
11-18 22:59:13.444 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onPause
11-18 22:59:13.584 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceDestroyed
11-18 22:59:17.794 5345-5345/com.bme.shawn.wobble D/WobbleActivity﹕ onResume
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceCreated
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ running to true
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleView﹕ surfaceChanged
11-18 22:59:17.804 5345-5345/com.bme.shawn.wobble D/WobbleThread﹕ setting surface sizes
11-18 22:59:17.824 5345-5345/com.bme.shawn.wobble D/dalvikvm﹕ GC_FOR_ALLOC freed 3343K, 2% free 6585K/6668K, paused 13ms, total 13ms
11-18 22:59:17.844 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 44
11-18 22:59:17.854 5345-5345/com.bme.shawn.wobble E/IMGSRV﹕ :0: PVRDRMOpen: TP3, ret = 50
Create a new instance of the thread in surfaceCreated() and start it. And call thread.join() in surfaceDestroyed()to destroy it.
I have been able to set up a connection between my socket server (running on ruby) and my client, which is an Android(java) application. I will explain what my goal is.
I have to send a string to my server through the socket. Depending on the contents of the string, the server would execute a process in the database (store, delete, view data, etc).
The first option is to validate the user name/password. Im able to send the correct string, and the server receives it and replies back to me with the correct response (after validating whether or not my username is capable of logging into the application). Now, depending on this response i need to change the current activity (loginActivity) with the next activity (MenuActivity) so that the user can proceed to use the application menu.
Since the socket has to run on a different thread other than the UIThread, im running it using the AsyncTask way. However im having problems triggering the activity change thing after the AsyncTask process is over.
What im doing is, after the whole Async task is done (onPostExecute method) im trying to call up the activity, but its not working. This is what i've tried (based on similar cases i've found during research):
(AsyncTask class)
Context context;
private void AppContext(Context context) {
this.context = context.getApplicationContext();
}
OnPostExecute
Intent NewActivity = new Intent();
NewActivity.setClass(context.getApplicationContext(),MainActivity.class);
context.startActivity(NewActivity);
However this is not working and its causing my app to crash with a "thread exciting with uncaught exception"
I've tried showing only a Toast message that says "Granted" or "Denied" just to test it with a simpler task, but i keep getting the same error so im assuming its got to do with handling the change between the thread on which the Async task is running and the UI thread. Any ideas?
P.S: I've checked the other questions that are similar to mine and tried the suggested code, but nothing's worked.
ERROR LOG
09-29 09:59:11.387: E/AndroidRuntime(2856): FATAL EXCEPTION: main
09-29 09:59:11.387: E/AndroidRuntime(2856): java.lang.NullPointerException
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.example.prescoterm.SocketClass.onPostExecute(SocketClass.java:111)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.example.prescoterm.SocketClass.onPostExecute(SocketClass.java:1)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask.finish(AsyncTask.java:602)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask.access$600(AsyncTask.java:156)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.Handler.dispatchMessage(Handler.java:99)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.os.Looper.loop(Looper.java:137)
09-29 09:59:11.387: E/AndroidRuntime(2856): at android.app.ActivityThread.main(ActivityThread.java:4424)
09-29 09:59:11.387: E/AndroidRuntime(2856): at java.lang.reflect.Method.invokeNative(Native Method)
09-29 09:59:11.387: E/AndroidRuntime(2856): at java.lang.reflect.Method.invoke(Method.java:511)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
09-29 09:59:11.387: E/AndroidRuntime(2856): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
09-29 09:59:11.387: E/AndroidRuntime(2856): at dalvik.system.NativeStart.main(Native Method)
Ok so i found a workaround this, now i would like to hear from you guys if you think this'd be a suitable solution.
Since the problem was that the context was coming up null at my AsyncTask class, i decided to load the value on a variable from the moment the application start.
context = this.getApplicationContext();
new SocketReception().setContext(context);
On my SocketReception Class i had a setContext(context) method.
public void setContext(Context context)
{
SocketReception.appContext= context;
};
Now, on my AsyncTask post.execute i call the new activity like this:
SocketReception.appContext.startActivity(NewActivity);
Its now working, but i want to know if this is a convenient approach or if i should keep looking for a different solution.
P.S: I had to add the unpopular "FLAG_ACTIVITY_NEW_TASK", will research on how to avoid this later on.
I have used this asynctask directly in activity and work fine, may be help. When i try call Intent i = new Intent(getApplicationContext(), VyberIcoActivitySD.class); in class without context ( class extended not Activity, Fragment... ) i have not result...
class SynchroAllIcosSD extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SynchroIcoActivitySD.this);
pDialog.setMessage(getString(R.string.progdata));
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
//do something
return null;
}
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
Intent i = new Intent(getApplicationContext(), VyberIcoActivitySD.class);
Bundle extras = new Bundle();
extras.putString("odkade", "100");
extras.putString("page", "1");
i.putExtras(extras);
startActivity(i);
finish();
}
});
}
}
I have this timer inside a service, it works perfectly and count... but when i call some asyntask's it gives me error!!
Timer time = new Timer(); // Instantiate Timer Object
time.schedule(new TimerTask(){
public void run() {
// i call my Asyntasks here
}
},5000,5000);
this gives me error:
03-17 02:02:27.167: E/AndroidRuntime(925): FATAL EXCEPTION: Timer-0
03-17 02:02:27.167: E/AndroidRuntime(925): java.lang.ExceptionInInitializerError
03-17 02:02:27.167: E/AndroidRuntime(925): at Dic.proj.pkg.notifService$1.run(notifService.java:57)
03-17 02:02:27.167: E/AndroidRuntime(925): at java.util.Timer$TimerImpl.run(Timer.java:289)
03-17 02:02:27.167: E/AndroidRuntime(925): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
03-17 02:02:27.167: E/AndroidRuntime(925): at android.os.Handler.<init>(Handler.java:121)
03-17 02:02:27.167: E/AndroidRuntime(925): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
03-17 02:02:27.167: E/AndroidRuntime(925): at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
03-17 02:02:27.167: E/AndroidRuntime(925): at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
03-17 02:02:27.167: E/AndroidRuntime(925): ... 2 more
if i put others instructions like Log.d("message"); everythings goes OK
AsynchTask needs to be created/called from a UI thread or at least a thread with a looper to handle callbacks when the task wants to publish anything to the caller thread such as onPostExcute() ... and using Timer object which runs in its own thread doesn't satisfy this condition.
I suggest you use Handler combined with Timer to achieve this, or even create your own timer using handler object.
The first idea would look something like this:
final Handler handler = new Handler();
Timer time = new Timer(); // Instantiate Timer Object
time.schedule(new TimerTask(){
public void run() {
handler.post(new Runnable(){
// i call my Asyntasks here
});
}
},5000,5000);
Take a look here to read more about Handlers and Timers:
Timer
AsynchTask
and here is a good tutorial about threads:
Tutorials
It seems, you should be inside UI-thread to start AsyncTasks.
You can try to use Handler.postDelayed(Runnale, long) instead of Timer.
The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
The task instance must be created on the UI thread.
You are creating a new thread. Use a handler. Runs on the main thread
private Handler handler = new Handler();
Runnable task = new Runnable() {
#Override
public void run() {
//do something
handler.postDelayed(this, 100000);
}
};
handler.removeCallbacks(task);
handler.post(task);
http://developer.android.com/reference/android/os/AsyncTask.html