Android: Как создать один (основной) экземпляр Activity или получить нужный мне экземпляр Activity? - PullRequest
1 голос
/ 27 сентября 2011

Я разрабатываю приложение для Android, которое выполняет поток и обновляет графический интерфейс через GUI Handler в GUI Activity.Мне нужно, чтобы поток запускался также, когда пользователь помещал приложение в фоновом режиме.Это сделано!

Моя проблема в том, что я хочу вернуться к действию, которое выполнялось ранее, когда пользователь возвращается к нему по истории приложений или по средствам запуска приложений.Вместо этого часто Android запускает новый экземпляр Activity.

Я пробовал использовать свойство приложения "launchMode" ("SingleTop", "SingleInstance", "SingleTask"), но не могу получить свою цель.

Альтернативный метод может заключаться в том, что я открываю уведомление от каждого действия, которое запускает поток, но как я могу открыть действие, «связанное» с этим уведомлением?

Надеюсь, что в вашей помощи

Спасибо

Редактировать: пример кода для простоты Я поместил весь код в один класс.

Если вы попробуете это приложение, нажмите кнопкувнизу и начинается нить.Теперь, если вы идете домой, открываете другие приложения, вы можете увидеть, что поток снова запущен, вы увидите тост (это то, что я хочу), затем, если вы вернетесь в мое приложение, или щелкнув уведомление или по программе запуска или по приложениюистория, новый экземпляр может быть создан, и я потерял предыдущий запуск.Как я могу решить это?Как я могу всегда возвращаться при выполнении действия?

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);
            }
        }
    }
}

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>

1 Ответ

0 голосов
/ 28 сентября 2011

Я решил!

Проблема была в кнопке «Назад», которая уничтожала активность. Затем у меня есть переопределить метод onBackPressed и спросить пользователя, если выйти или оставить действие активным. Более того, я установил launchMode = "singleTop" , это то, что мне нужно.

Это было проще, чем я думал;)

Но У меня есть сомнение: как приложение может работать после уничтожения? Тост был виден и после того, как была нажата кнопка назад. Что тогда уничтожается?

...