2014-04-01 88 views
2

当用户使用BACK按钮退出应用程序时,Android中的后台服务停止运行。如果应用程序处于前景或背景中,则相同的服务可以正常工作(单击HOME按钮)。当应用程序通过BACK按钮关闭时,后台服务停止

有三种情况:

  1. 保持该应用运行:每15秒的通知显示(OK)。
  2. 通过单击HOME按钮把应用程序在后台:通知使显示(OK)
  3. 单击后退按钮(这将关闭应用程序):后台服务被停止,并没有更多的通知显示(BUG)

预期行为

同样在案例#3中,通知应该每隔15秒继续运行一次。

我的整个源代码如下

MainActivity.java

package com.example.service_demo; 

import android.app.Activity; 
import android.app.ActivityManager; 
import android.app.ActivityManager.RunningServiceInfo; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 

public class MainActivity extends Activity implements OnClickListener { 

    private TextView timerValue; 
    private Button startTimer; 
    private Button cancleTimer; 
    Intent i; 

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

    } 

    private void mapview() { 

     timerValue = (TextView) findViewById(R.id.timertext); 
     startTimer = (Button) findViewById(R.id.starttimer); 
     cancleTimer = (Button) findViewById(R.id.cancletimer); 
     startTimer.setOnClickListener(this); 
     cancleTimer.setOnClickListener(this); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     i = new Intent(this, SimpleService.class); 
     if (isMyServiceRunning()) { 
      Toast.makeText(getBaseContext(), "Service is running,", 
        Toast.LENGTH_SHORT).show(); 
      registerReceiver(broadcastReceiver, new IntentFilter(
        SimpleService.BROADCAST_ACTION)); 
      startTimer.setEnabled(false); 
     } else { 
      Toast.makeText(getBaseContext(), "There is no service running", 
        Toast.LENGTH_SHORT).show(); 
     } 

    } 

    @Override 
    public void onClick(View v) { 
     if (v == startTimer) { 
      startTimer.setEnabled(false); 
      i = new Intent(this, SimpleService.class); 
      startService(i); 
      registerReceiver(broadcastReceiver, new IntentFilter(
        SimpleService.BROADCAST_ACTION)); 
     } else if (v == cancleTimer) { 
      i = new Intent(this, SimpleService.class); 
      stopService(i); 
      timerValue.setText("00:00:00"); 
      startTimer.setEnabled(true); 

     } 
    } 

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 

      updateUI(intent); 
     } 

    }; 

    private void updateUI(Intent intent) { 
     String str = intent.getStringExtra("textval"); 
     timerValue.setText(str); 

    } 

    private boolean isMyServiceRunning() { 
     ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
     for (RunningServiceInfo service : manager 
       .getRunningServices(Integer.MAX_VALUE)) { 
      if (SimpleService.class.getName().equals(
        service.service.getClassName())) { 
       return true; 
      } 
     } 
     return false; 
    } 

    @Override 
    protected void onStop() { 
     // TODO Auto-generated method stub 
     super.onStop(); 
     i = new Intent(this, SimpleService.class); 
     startService(i); 
    } 

    @Override 
    public void onBackPressed() { 
     // TODO Auto-generated method stub 
     super.onBackPressed(); 
     System.exit(0); // system.exit(0) is mendatory for my app so it can't be 
         // removed 
    } 

} 

SimpleService

package com.example.service_demo; 

import java.util.Timer; 
import java.util.TimerTask; 

import android.os.Binder; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.app.Activity; 
import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.Toast; 

public class SimpleService extends Service { 

    private NotificationManager mNM; 
    private long startTime = 0L; 
    long timeInMilliseconds = 0L; 
    long timeSwapBuff = 0L; 
    long updatedTime = 0L; 
    long basestart = System.currentTimeMillis(); 
    Timer timer = new Timer(); 
    long timeswap = 0L; 
    int secs = 0; 
    int mins = 0; 
    int hour = 0; 
    Intent intent; 
    String s; 
    public static final String BROADCAST_ACTION = "com.example.service_demo.MainActivity"; 
    private int NOTIFICATION = 1; 

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

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
     intent = new Intent(BROADCAST_ACTION); 
     Toast.makeText(this, "Service Started", 2000).show(); 

    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     Thread t = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       timer.schedule(new RemindTask(), 0, 1000); 
      } 
     }); 
     t.start(); 

     return Service.START_NOT_STICKY; 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 

     mNM.cancel(NOTIFICATION); 

     if (timer != null) { 
      timer.cancel(); 
      timer.purge(); 
      timer = null; 
     } 
     Toast.makeText(this, "Service Stoped", 2000).show(); 
    } 

    class RemindTask extends TimerTask { 

     @Override 
     public void run() { 

      timeInMilliseconds = System.currentTimeMillis() - basestart; 
      timeSwapBuff = timeswap; 
      updatedTime = timeSwapBuff + timeInMilliseconds; 

      secs = (int) (updatedTime/1000); 
      mins = secs/60; 
      hour = mins/60; 

      secs = secs % 60; 
      mins = mins % 60; 

      s = "" + String.format("%02d", hour) + ":" + "" 
        + String.format("%02d", mins) + ":" 
        + String.format("%02d", secs); 
      if (s.equalsIgnoreCase("00:00:15")) { 
       showNotification(); 
      } 
      intent.putExtra("textval", s); 
      sendBroadcast(intent); 
     } 
    } 

    private void showNotification() { 
     // In this sample, we'll use the same text for the ticker and the 
     // expanded notification 
     CharSequence text = s; 

     // Set the icon, scrolling text and timestamp 
     @SuppressWarnings("deprecation") 
     Notification notification = new Notification(R.drawable.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, "Notification Label", text, 
       contentIntent); 

     // Send the notification. 
     mNM.notify(NOTIFICATION, notification); 
    } 

} 
+0

嘿你为什么要使用System.exit(0);你可以删除然后尝试。 – MPG

+0

而不是显示一个吐司,你可以尝试打印日志,看看它是否工作,即使应用程序退出后。 –

回答

0

尝试实施前景的服务。 foreground service

前台服务显示通知并且从不停止。

在你的服务的onCreate()中实现这个代码片段。

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), 
     System.currentTimeMillis()); 
Intent notificationIntent = new Intent(this, ExampleActivity.class); 
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); 
notification.setLatestEventInfo(this, getText(R.string.notification_title), 
     getText(R.string.notification_message), pendingIntent); 
startForeground(ONGOING_NOTIFICATION_ID, notification); 
+0

我可以把通知任务放在前台,但我想要的是我的计时器应该继续运行,直到我按停止计时器按钮。我的意思是说,当我的计时器字符串是00:00:15时,我必须得到通知,并且只要我重新启动我的应用程序,并按下按钮 – Jigar

+0

就可以继续运行,那么您可以在Service类中运行您的计时器,当你回去时不会停下来。当按钮被点击时停止你的服务。 –

+0

我的计时器在服务类本身中运行。只需再次检查代码 – Jigar

1

在服务的方法onStartCommand(),返回START_STICKY。 服务将继续运行,直到您明确地在服务中调用stopSelf()或从您的活动中调用stopService()

+0

在服务的方法onStartCommand(),如果我使用START_STICKY然后如果我按回来按钮,并再次启动应用程序比它将从00:00:00开始计时器。 但我希望我的计时器继续运行,直到我按停止计时器按钮 – Jigar

+1

每次我重新启动应用程序而不是连续计时器时,START_STICKY会从“00:00:00”创建一个新计时器 – Jigar

+0

听起来像您的应用程序启动器活动的onCreate ()方法每次都会重新启动服务,您可以在服务中使用布尔值来指示它是运行还是净值。如果它正在运行,请不要启动计数器 – elmorabea

0

这个工作对我来说:

notifyIntent.setAction(Intent.ACTION_MAIN); 
notifyIntent.addCategory(Intent.CATEGORY_LAUNCHER); 
相关问题