开发者

Android: How to have a single (main) Activity instance or retrieve the Activity instance that I need?

I am developing an Android app that execute a thread and update the GUI via a GUI Handler on GUI Activity. I need that the thread runs also when the user put the app in background. This is done!

My problem is that I want to return to the Activity that was running before when the user return to it by app history or by apps launcher. Instead many often Android launch a new Activity instance.

I have tried with application property "launchMode" ("SingleTop", "SingleInstance", "SingleTask"), but I can't obtain my goal.

An alternative method could be that I open a notification from every Activity that run a thread, but how can I do to open the Activity "linked" to that notification?

I hope in your help

Thank you

Edit: sample code for simplicity I have put all code in a single class.

If you try this app, press the button on the bottom and the thread starts. Now if you go to home open other apps, you can see that the thread is again running, you see the toast (this is what I want), Then if you return on my app, or by clicking notification or by launcher or by app history, a new instance can be created and I lost the previous running. How can I solve this? How can I return always on running activity?

TestThreadActivity.java

package tld.test;

import java.util.ArrayList;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class TestThreadActivity extends Activity {

    private static final int NOTIFY_THREAD_IS_RUNNING = 1;
    private MyRunnable myRunnable;
    private Thread myThread;
    // List of all message
    private ArrayList<String> responseList = new ArrayList<String>(10);
    // ListView adapter
    private ArrayAdapter<String> responseListAdapter;

    /**
     * Called when the activity is first created.
     **/
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        responseListAdapter = new ArrayAdapter<String>(this,
            R.layout.list_item, responseList);
        ListView listViewResponse = (ListView) findViewById(R.id.listViewResponse);
        listViewResponse.setAdapter(responseListAdapter);
        ToggleButton toggleButton = (ToggleButton) findViewById(R.id.startStopBtn);
        toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {

             @Override
             public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
                if (isChecked)
                    startThread();
                else
                    stopThread();
             }
        });
    }

    /**
     * Create and start the thread
     **/
    private void startThread() {
        // Clear listview
        responseList.clear();
        responseListAdapter.notifyDataSetChanged();
        if (myRunnable == null)
        myRunnable = new MyRunnable(guiHandler);
        myThread = new Thread(myRunnable, "myThread-" + System.currentTimeMillis());
        myThread.start();
        notifyThread();
        Toast.makeText(this, "Thread Started", Toast.LENGTH_SHORT).show();
    }

    /**
     * Stop the thread
     **/
    private void stopThread() {
        myRunnable.stop();
        cancelNotifyThread();
        Toast.makeText(this, "Thread Stopped", Toast.LENGTH_SHORT).show();
    }

    /**
     * Crea una notifica sulla barra di stato
     */
    private void notifyThread() {
        int icon = R.drawable.icon; // default icon from resources
        CharSequence tickerText = "Thread is running"; // ticker-text       
        long when = System.currentTimeMillis(); // notification time
        Context context = getApplicationContext(); // application Context
        CharSequence contentTitle = getString(R.string.app_name); // expanded
                                                                // message
                                                                // title
        CharSequence contentText = "Thread is running..."; // expanded message
                                                            // text
        Intent notificationIntent = new Intent(this, this.getClass());
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);
        // the next two lines initialize the Notification, using the
        // configurations above
        Notification notification = new Notification(icon, tickerText, when);
        notification.flags |= Notification.FLAG_ONGOING_EVENT;
        notification.setLatestEventInfo(context, contentTitle, contentText,
            contentIntent);
        NotificationManager notificationManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
        notificationManager.notify(NOTIFY_THREAD_IS_RUNNING, notification);
    }

    /**
     * Clear previous notification
     */
    private void cancelNotifyThread() {
        NotificationManager notificationManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
        notificationManager.cancel(NOTIFY_THREAD_IS_RUNNING);
    }

    // My GUI Handler. Receive message from thread to put on Activity's listView
    final private Handler guiHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
                String newMsg = (String) msg.obj;
                // Add message to listView
            responseList.add(newMsg);
            responseListAdapter.notifyDataSetChanged();
                // and show a toast to view that is running also when it is not in
            // foreground.
            Toast.makeText(TestThreadActivity.this, newMsg, Toast.LENGTH_SHORT)
                .show();
            super.handleMessage(msg);
        }
    };

    /**
     * Simple runnable. Only wait WAIT_INTERVAL milliseconds and send a message
     * to the GUI
     **/
    public class MyRunnable implements Runnable {
        public static final int WHAT_ID = 1;
        private static final int WAIT_INTERVAL = 5000;
        private boolean isRunning;
        private int counter;
        private Handler guiHandler;

        public MyRunnable(Handler guiHandler) {
            super();
            this.guiHandler = guiHandler;
        }

        public void stop() {
            isRunning = false;
        }

        @Override
        public void run() {
            counter = 0;
            isRunning = true;
            while (isRunning) {
                // Pause
                try {
                    Thread.sleep(WAIT_INTERVAL);
                } catch (InterruptedException e) {
                }
                // Notify GUI
                Message msg = guiHandler.obtainMessage(WHAT_ID,
                    "Thread is running: " + (++counter) + " loop");
                guiHandler.sendMessage(msg);
          开发者_C百科  }
        }
    }
}

layout\main.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">
    <ListView android:layout_width="match_parent" android:id="@+id/listViewResponse"
        android:layout_height="0dip" android:layout_weight="1.0" android:transcriptMode="normal"></ListView>
    <ToggleButton android:id="@+id/startStopBtn"
        android:layout_height="wrap_content" android:layout_width="match_parent" android:textOn="@string/toggleBtnStop" android:textOff="@string/toggleBtnStart"></ToggleButton>
</LinearLayout>

layout\list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>

values\strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">TestThread</string>
    <string name="toggleBtnStart">Start Thread</string>
    <string name="toggleBtnStop">Stop Thread</string>
</resources>


I have solved!

The problem was the Back button that destroy the activity. Then I have override onBackPressed method and ask user if quit or leave activity running. Moreover I have set launchMode="singleTop" that is what I need.

It was easier than I thought ;)

But I have a doubt: How could app running after destroy? The toast was visible also after thath back button was pressed. What is destroyed then?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜