重新打开和关闭应用程序时,Android服务停止

时间:2014-07-12 13:06:49

标签: java android service

我试图了解android服务的工作原理。

所以我创建了一个包含活动和服务的简单应用程序,有代码:

MainActivity.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Service"
        android:id="@+id/buttonStart"
        android:layout_marginTop="60dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:onClick="startButtonClickHandler"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop Service"
        android:id="@+id/buttonStop"
        android:layout_below="@+id/buttonStart"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:enabled="false"
        android:onClick="stopButtonClickHandler" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/textView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:text="Counter is: 0" />

</RelativeLayout>

MainActivity.java:

package com.example.wellsaid.provaservice;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;


public class MainActivity extends Activity {

    Button btn_stop = null;
    Button btn_start = null;

    /*---------------------------- CODICE NUOVO -----------------------------*/
    private class MyReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            int datapassed = arg1.getIntExtra("count", 0);
            TextView text = (TextView) findViewById(R.id.textView);
            text.setText("Counter is: " + datapassed);
        }

    }

    MyReceiver myreceiver = null;
    /*---------------------------------------------------------------------*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_stop = (Button) findViewById(R.id.buttonStop);
        btn_start = (Button) findViewById(R.id.buttonStart);
        if(ExampleService.isRunning()){
            btn_stop.setEnabled(true);
            btn_start.setText("Send request");
            Intent intent = new Intent(this, ExampleService.class);
            intent.putExtra("count",0);
            startService(intent);
        }

        /*--------------------- CODICE NUOVO -------------------------------*/
        myreceiver = new MyReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ExampleService.RETURN_COUNTER);
        registerReceiver(myreceiver, intentFilter);
        /*------------------------------------------------------------------*/
    }

    public void startButtonClickHandler(View v){
        if(!btn_stop.isEnabled()) {
            btn_stop.setEnabled(true);
            btn_start.setText("Send request");
        }
        Intent intent = new Intent(this, ExampleService.class);
        intent.putExtra("count",0);
        startService(intent);
    }

    public void stopButtonClickHandler(View v){
        Intent intent = new Intent(this, ExampleService.class);
        stopService(intent);
        btn_start.setText("Start Service");
        btn_stop.setEnabled(false);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        unregisterReceiver(myreceiver);
        super.onStop();
    }

}

ExampleService.java

package com.example.wellsaid.provaservice;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;


public class ExampleService extends Service {

    /*--------------------- CODICE NUOVO-------------------------------*/
    final static String RETURN_COUNTER = "RETURN_COUNTER";
    /*----------------------------------------------------------------*/

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        Intent intent = new Intent(this, ExampleService.class);
        intent.putExtra("count",thread.getCounter());
        startService(intent);
    }

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

    ExampleThread thread = null;
    private static boolean running = false;

    public static boolean isRunning() { return running; }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        running = true;
        if(thread == null) {
            int counter = intent.getExtras().getInt("count");
            thread = new ExampleThread(counter);
            thread.start();
        }
        else{
            /*-----------------------CODICE NUOVO ----------------------*/
            Intent send = new Intent();
            send.setAction(RETURN_COUNTER);
            send.putExtra("count",thread.getCounter());
            sendBroadcast(send);
            /*----------------------------------------------------------*/
        }
        return startId;
    }

    @Override
    public void onDestroy() {
        running = false;
        thread.kill();
        super.onDestroy();
    }

    private class ExampleThread extends Thread {

        boolean stopped;
        int counter = 0;

        public ExampleThread(int counter){
            this.counter = counter;
        }

        public void start(){
            stopped = false;
            super.start();
        }

        public int getCounter(){ return counter; }

        public void kill(){
            stopped = true;
        }

        public void run(){
            while(!stopped) {
                try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
                counter++;
                Log.i("Service", "Counter is: " + counter);
            }
        }
    }
}

这就是我的表现:

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/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=".ExampleService" />

    </application>

</manifest>

我尝试过:1)打开应用程序,使用启动按钮启动服务,然后用另一个停止它。一切OK 2)打开应用程序,启动服务并关闭应用程序。一切OK(服务仍在运行)3)打开应用程序,启动服务,重新打开应用程序并获取计数器值。一切OK 4)打开应用程序,启动服务,关闭应用程序,重新打开应用程序并停止服务。一切OK(关闭后也重启服务) 当我打开,启动服务,关闭应用程序,重新打开以检查计数器编号然后再次关闭应用程序时出现问题,一段时间后服务停止,logcat中没有消息:( 在应用程序管理的我的Android设备上,我可以看到我的应用程序处于重新启动状态,经过很长时间后,它会重新启动,然后再次停止,打开等等.... 我已经在三星Galaxy express stock(android 4.1.2)和三星galaxy tab 2 10.1上测试了cyanogenmod 10.1.3(android 4.2.2)

1 个答案:

答案 0 :(得分:0)

您是否通读了https://developer.android.com/reference/android/app/Service.html

请注意以下事项:

  

对于已启动的服务,还有两种主要模式   根据他们的价值,他们可以决定参加比赛   从onStartCommand()返回:START_STICKY用于那些服务   根据需要显式启动和停止,同时START_NOT_STICKY   或START_REDELIVER_INTENT仅用于服务   在处理发送给他们的任何命令时保持运行。

来自START_STICKY文档:

  

从onStartCommand(Intent,int,int)返回的常量:如果是这样   服务的进程在启动时被终止(在返回之后)   onStartCommand(Intent,int,int)),然后将其保持在启动状态   但不要保留这个意图。稍后系统会尝试   重新创建服务。因为它处于启动状态,它会   保证在创建后调用onStartCommand(Intent,int,int)   新服务实例;如果没有任何挂起的启动命令   如果被传递给服务,它将被调用null意图   对象,所以你必须注意检查这个。

     

此模式适用于将明确启动的内容   停止运行任意时间段,例如服务   表演背景音乐播放。