2014-07-12 94 views
1

我试图了解Android服务如何工作。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)打开应用程序,在开始按钮来启动服务,并与其他阻止它。并且一切正常2)打开应用程序,启动服务并关闭应用程序。并且一切正常(服务仍在运行)3)打开应用程序,启动服务,重新打开应用程序并获取计数器值。并且都可以4)打开应用程序,启动服务,关闭应用程序,重新打开应用程序并停止服务。并且一切正常(关闭后也重新启动服务) 当我打开,启动服务,关闭应用程序,重新打开以检查计数器编号,然后再关闭应用程序时,显示问题,过了一会儿服务停止,logcat中没有消息: ( 在我的应用程序管理Android设备上,我可以看到我的应用程序在重新启动状态,经过很长时间后重新启动,然后再次停止,继续...... 我测试过三星Galaxy Express股票(安卓4.1.2)和三星Galaxy Tab 2 10.1与10.1.3的CyanogenMod(安卓4.2.2)

回答

0

你读过通过https://developer.android.com/reference/android/app/Service.html

注意以下几点:?

对于启动的服务,也有 操作的另外两个主要模式,他们可以决定是否在运行,这取决于他们 从onStartCommand()返回值:START_STICKY用于那些 明确启动和停止的服务而START_NOT_STICKY 或START_REDELIVER_INTENT用于在处理发送给它们的任何命令时应该仅保留运行的服务。

START_STICKY文档:

不断从onStartCommand(意向,INT,INT)返回:如果当它开始这个 服务的进程被终止(从 onStartCommand(意向回国后, int,int)),然后将其保留在开始状态 ,但不保留此传递的意图。稍后系统会尝试 重新创建服务。由于它处于启动状态,因此 保证在创建 新服务实例后调用onStartCommand(Intent,int,int);如果没有任何挂起的启动命令将 传送到服务中,则将以空对象 对象调用它,因此您必须小心检查此操作。

该模式对于明确开始的事物以及 停止运行任意时间段(例如执行背景音乐播放的服务 )有意义。

+0

嗨,谢谢你的回复。是的,我已阅读该页面,但返回START_STICKY没有帮助我,现在我正在重试START_STICKY并添加一个startForeground语句在示例服务类 –

+0

的构造函数中的if(线程== null)块似乎工作:D我已经完成了主题中的所有测试,并且仍然没有错误地运行。谢谢:) –

+0

我很高兴你设法让它工作。如果我的回答以任何方式帮助你,你可以接受它。否则,为了对已接受的答案有疑问,请详细说明您在另一个答案中所做的并接受它。 –

相关问题