Maverick
Maverick

Reputation: 2760

How to stop or destroy an Android thread

I know that the stop method has been deprecated and I am using destroy now, but I get this error:

11-09 11:42:28.740: E/AndroidRuntime(1538): FATAL EXCEPTION: main
11-09 11:42:28.740: E/AndroidRuntime(1538): java.lang.NoSuchMethodError: Thread.destroy()
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.Thread.destroy(Thread.java:600)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.rathbones.src.NewslettersActivity.onKeyDown(NewslettersActivity.java:144)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.app.Activity.dispatchKeyEvent(Activity.java:2068)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.os.Looper.loop(Looper.java:123)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.app.ActivityThread.main(ActivityThread.java:4627)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.reflect.Method.invokeNative(Native Method)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.reflect.Method.invoke(Method.java:521)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at dalvik.system.NativeStart.main(Native Method)
11-09 11:42:28.760: W/ActivityManager(59):   Force finishing activity com.rathbones.src/.NewslettersActivity

The application is not crashing, it's just that I get this error in logcat.

Actually I have a newsletter module which enables users to view the PDF file. When they press the view button it opens up a progress bar and in the same time if someone presses the backbutton it should stop the thread and exit gracefully. It does that but in the log I get the above error.

Here is the code snippet causing this error:

private void viewOnline() {

        if (currentNewsletter == null) {
            Log.e(Constants.APP_NAME, "No newsletter selected");
            return;
        }

        final ProgressDialog d = new ProgressDialog(this);
        d.setMessage("Downloading...");
        d.show();

        final Context context = getApplicationContext();
         t = new Thread(new Runnable() {
            public void run() {

                String fileName = currentNewsletter.mFilename;

                Log.d(Constants.APP_NAME, "Downloading/showing: " + fileName);
                final File file = Utilities.getFileFromURL(context, currentNewsletter.mUrl, currentNewsletter.mExpectedSizeInBytes, fileName, false);

                d.dismiss();
                // Now we can show the file
                viewPDF(file);
            }
        });
        t.start();

        // Utilities.List(getApplicationContext().getFilesDir().getPath());
        // Utilities.List(getApplicationContext().getDir("files", Context.MODE_WORLD_WRITEABLE).getAbsolutePath());
        // Utilities.DeleteDirectory(getApplicationContext().getDir("files", Context.MODE_WORLD_WRITEABLE).getAbsolutePath());

    }

    private void viewPDF(File file) {

        //DEBUG DEBUG DEBUG
        //Log.d(Constants.APP_NAME, "ViewPDF: showing " + file.getName());
        //Log.d(Constants.APP_NAME, "Path: " + file.getPath());
        //Log.d(Constants.APP_NAME, "Exists: " + file.exists());
        //Log.d(Constants.APP_NAME, "Length: " + file.length());
        //DEBUG DEBUG DEBUG

        // Now it's all safe and sound and local, open it
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file), "application/pdf");

        try {
            startActivity(intent);
        } catch (Exception e) {
            Toast.makeText(this, "No Application Available to View PDF", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onStop() {
        finish();
        super.onStop();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            t.destroy();
           Intent i = new Intent(NewslettersActivity.this,MainMenuActivity.class);

           startActivity(i);
           finish();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

Upvotes: 1

Views: 11281

Answers (3)

user370305
user370305

Reputation: 109257

If you have a thread with a while loop inside, you can control this thread by a boolean flag for the while condition. When you set the flag to false the thread just finishes its task.

Here's a little example:

boolean flag = true;
Thread secondary = new Thread(new Runnable() {

@Override
public void run() {
    while (flag) {
    // do something
    }
 }
});

secondary.start(); //start the thread
flag = false; // this will force secondary to finish its execution
 try {
   secondary.join(); // wait for secondary to finish
   } catch (InterruptedException e) {
    throw new RuntimeException(e);
}

I will found this code in SO and it also works for me.

Upvotes: 3

Raúl Torres
Raúl Torres

Reputation: 1

To the user370305 answer, maybe two changes could help:

  1. Use AtomicBoolean instead boolean, if the Thread runs in another core, changes could not be visible for flag.

  2. Remove the throw new RuntimeException(e) within the catch. It will crash as you are throwing an Exception.

Upvotes: 0

Quentin DOMMERC
Quentin DOMMERC

Reputation: 876

Use interrupt() instead of destroy().

Upvotes: 2

Related Questions