在后退按钮" IllegalStateException:在onSaveInstanceState"之后无法执行此操作

时间:2015-04-10 08:59:39

标签: android android-activity service

关于这个有很多问题和答案,但我无法找到解决方案。

简单的服务和活动。 在活动中一个按钮用于连接和本地绑定到服务。其他按钮从MyService获取一个随机数。

当我停止绑定时,停止服务并按下后退按钮“IllegalStateException”发生。如何解决此错误?

MainActivity.java

package expandev.com.myapplication;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;


public class MainActivity extends ActionBarActivity {
    TextView txtStatus, txtRandomValue;
    Button btnRandButton;
    ToggleButton tbtnServiceButton;

    MyService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtStatus = (TextView)findViewById(R.id.textStatus);
        txtRandomValue = (TextView)findViewById(R.id.textRandomValue);

        CheckIfServiceIsRunning();
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            MyService.LocalBinder binder = (MyService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    public void onRandButtonClicked(View v) {
        if (mBound) {
            int num = mService.getRandomNumber();
            txtRandomValue.setText("number: " + num);
        }
    }

    public void onServiceButtonClicked(View view) {

        // Is the toggle on?
        boolean on = ((ToggleButton) view).isChecked();

        if (on) {
            super.onStart();
            startService(new Intent(getBaseContext(), MyService.class));
            doBinding();
            txtStatus.setText("Service on");
        } else {
            super.onStop();
            doUnBinding();
            stopService(new Intent(getBaseContext(), MyService.class));
            txtStatus.setText("Service off.");
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void CheckIfServiceIsRunning() {
        if (MyService.isRunning()) {
            doBinding();
            txtStatus.setText("Service on");
            ToggleButton toggleGPS = (ToggleButton)findViewById(R.id.tbtnServiceButton);
            toggleGPS.setChecked(true);
        }
    }

    private void doBinding() {
        Intent intent = new Intent(this, MyService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private void doUnBinding() {
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

MyService.java

package expandev.com.myapplication;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import java.util.Random;

public class MyService extends Service {
    private NotificationManager nm;
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();
    //Service is Running
    private static boolean isRunning = false;



    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        MyService getService() {
            // Return this instance of LocalService so clients can call public methods
            return MyService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public int getRandomNumber()
    {
        return mGenerator.nextInt(100);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Let it continue running until it is stopped.
        //Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }

    public static boolean isRunning()
    {
        return isRunning;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
        nm.cancel(R.string.remote_service_started);
        isRunning = false;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        showNotification();
        isRunning = true;
    }

    private void showNotification() {
        nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.remote_service_started);
        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.mipmap.ic_launcher, text, System.currentTimeMillis());
        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.service_label), text, contentIntent);
        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        nm.notify(R.string.remote_service_started, notification);
    }
}

ActivityMain.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="20dp"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <RelativeLayout android:id="@+id/RelativeLayout01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <TextView android:id="@+id/textStatus"
            android:textSize="24sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Status Goes Here" />

        <TextView android:id="@+id/textRandomValue"
            android:textSize="24sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Random Value Goes Here"
            android:layout_below="@+id/textStatus"/>

    </RelativeLayout>

    <RelativeLayout android:id="@+id/RelativeLayout02"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp">

    <Button
        android:id="@+id/btnRandButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Random Number"
        android:onClick="onRandButtonClicked"
        android:clickable="true">
    </Button>

    <ToggleButton
        android:id="@+id/tbtnServiceButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textOn="Stop Service"
        android:textOff="Start Service"
        android:onClick="onServiceButtonClicked"
        android:clickable="true"
        android:layout_alignParentRight="true">
    </ToggleButton>

    </RelativeLayout>

</LinearLayout>

的Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="expandev.com.myapplication" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true" >
        </service>
    </application>

</manifest>

build.gradle(app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "expandev.com.myapplication"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
}

logcat的

04-10 09:25:04.526  24836-24836/expandev.com.myapplication W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
04-10 09:25:04.526  24836-24836/expandev.com.myapplication W/dalvikvm﹕ threadid=1: calling UncaughtExceptionHandler
04-10 09:25:04.526  24836-24836/expandev.com.myapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
            at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1375)
            at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:502)
            at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:176)
            at android.support.v7.app.ActionBarActivity.onBackPressed(ActionBarActivity.java:295)
            at android.app.Activity.onKeyUp(Activity.java:2156)
            at android.view.KeyEvent.dispatch(KeyEvent.java:2679)
            at android.app.Activity.dispatchKeyEvent(Activity.java:2393)
            at android.support.v7.app.ActionBarActivity.dispatchKeyEvent(ActionBarActivity.java:523)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1885)
            at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:4201)
            at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:4144)
            at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3213)
            at android.os.Handler.dispatchMessage(Handler.java:107)
            at android.os.Looper.loop(Looper.java:194)
            at android.app.ActivityThread.main(ActivityThread.java:5405)
            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:838)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
            at dalvik.system.NativeStart.main(Native Method)

2 个答案:

答案 0 :(得分:1)

Insdie public void onServiceButtonClicked(View view) 删除此行
super.onStop();

重要:停止/销毁活动时取消绑定服务。

答案 1 :(得分:0)

只需将ActionBarActivity更改为Activity即可。您的代码将运行。