无法停止后台服务android

Posted

技术标签:

【中文标题】无法停止后台服务android【英文标题】:Can't stop background service android 【发布时间】:2015-12-17 06:08:25 【问题描述】:

我正在运行以下后台服务:

public class TranslationService  extends IntentService implements ClipboardManager.OnPrimaryClipChangedListener 

    private Language mFrom;
    private Language mTo;
    private String mTranslation;
    private ClipboardManager mClipboardManager;

    public TranslationService() 
        super("hello");
    

    public TranslationService(String name) 
        super(name);
    

    @Override
    protected void onHandleIntent(Intent intent) 

    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        mFrom = (Language) intent.getSerializableExtra(MainActivity.FROM_STRING);
        mTo = (Language) intent.getSerializableExtra(MainActivity.TO_STRING);
        mClipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        mClipboardManager.addPrimaryClipChangedListener(this);

        return super.onStartCommand(intent, flags, startId);
    

    @Override
    public void onPrimaryClipChanged() 

        ClipData clip = mClipboardManager.getPrimaryClip();
        String copiedText = clip.getItemAt(0).getText().toString();
        connectToTranslationApi(copiedText);

        //TODO solve concurrency problems if app works inconsistently.
        try 
           Thread.sleep(500);
         catch (InterruptedException e) 
           e.printStackTrace();
        

            new Handler(Looper.getMainLooper()).post(new Runnable() 
                @Override
                public void run() 
                    Toast.makeText(getBaseContext(), mTranslation, Toast.LENGTH_SHORT).show();
                
            );

    

    private void connectToTranslationApi(String copiedPhrase) 

        String apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
        String fromInitials = mFrom.initials;
        String toInitials = mTo.initials;
        String yandexUrl = "https://translate.yandex.net/api/v1.5/tr.json/translate?key="+
                apiKey + "&lang=" +
                fromInitials + "-" + toInitials +
                "&text="+ copiedPhrase;

        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(yandexUrl).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() 
            @Override
            public void onFailure(Request request, IOException e) 
                //TODO handle failure
            

            @Override
            public void onResponse(Response response) throws IOException 
                if (response.isSuccessful()) 
                    String jsonData = response.body().string();
                    try mTranslation = getTextTranslation(jsonData);
                    catch (JSONException e) e.printStackTrace();
                
            
        );
    

    private String getTextTranslation(String jsonData) throws JSONException 
        JSONObject data = new JSONObject(jsonData);
        String translation = data.getString("text");
       translation = translation.replace("]", "")
                    .replace("[", "")
                    .replace("\"", "");
        return translation;
    


该服务在后台运行并翻译我复制到剪贴板的文本(即使我使用其他应用程序。只有当我从 RAM 中删除启动它的应用程序时,该服务才会停止),这一切都很好。

但是,当我回到应用程序的主要活动并按“停止服务”时,它不会停止。这是启动(并应该停止)服务的代码

         if(mIsServiceRunning == false) 
            Intent i = new Intent(MainActivity.this, TranslationService.class);
            i.putExtra(FROM_STRING, mLanguageFrom);
            i.putExtra(TO_STRING, mLanguageTo);
            startService(i);
            mIsServiceRunning = true;
            startButton.setText("Stop Service");
            Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
        
        else 
            Intent i = new Intent(MainActivity.this, TranslationService.class);
            stopService(i);
            mIsServiceRunning = false;
            startButton.setText("Start Service");
        

任何想法如何阻止它?

【问题讨论】:

你怎么知道它没有停止? 【参考方案1】:

我不完全确定您如何确定您的服务仍在运行。 但我建议不要基于 mIsServiceRunning 布尔值。

您可以使用此方法来确保它是否正在运行:

public static boolean isServiceRunning(Class<?> serviceClass) 
  ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
  for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
    if (serviceClass.getName().equals(service.service.getClassName())) 
      return true;
    
  
  return false;

此方法将返回一个布尔值,告诉您服务是否在后台运行, 例如,您可以像这样使用它:

if (isServiceRunning(TranslationService.class)) 
  Toast.makeText(this, "Service is Running", Toast.LENGTH_SHORT).show();
 else 
  Toast.makeText(this, "Service is NOT Running", Toast.LENGTH_SHORT).show();

也许我也错过了它,但我在您的代码中看不到任何错误。

context.stopService(new Intent(context, TranslationService.class));

应该停止你的服务。

希望对您有所帮助,如果没有,请尝试在您尝试后提供更多信息。

【讨论】:

好吧,每次我复制到剪贴板时仍然会弹出一个翻译,这样做的方法是在服务的类中,所以我看不出它怎么可能没有运行。顺便说一句,在您建议的代码中,在 WorkoutApplication.getInstance() 我应该用什么替换 WorkoutApplication? 抱歉,我会编辑一下,WorkoutApplication.getInstance() 是上下文。【参考方案2】:

存在内存泄漏,因为您在未销毁剪贴板方法的情况下离开了它。 在特定活动被破坏后,您需要从 ram 中创建清除剪贴板对象的侦听器。尽管服务已停止,但此剪贴板方法在内存中运行。您需要通过此代码停止

clipboardManager.removePrimaryClipChangedListener(listener);

在任何 onDestroy(),onPause() 方法上。

试着理解下面的代码

public class MySecretService extends Service 

ClipboardManager clipboardManager;
ClipData clipData;
ClipData.Item item;
String text;
//declare Listener 
ClipboardManager.OnPrimaryClipChangedListener listener;

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


@Override
public void onCreate() 
    Toast.makeText(this, "Service is Started !!!", Toast.LENGTH_SHORT).show();
    clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);




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

    Toast.makeText(this, "Service is Created !!! ", Toast.LENGTH_SHORT).show();
    //fire intent
    intent = new Intent(MySecretService.this, DictionaryActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    final Intent finalIntent = intent;

    //asign listener to onPrimaryClipChangedListner 
    clipboardManager.addPrimaryClipChangedListener(listener = new ClipboardManager.OnPrimaryClipChangedListener() 
        @Override
        public void onPrimaryClipChanged() 
            clipData = clipboardManager.getPrimaryClip();
            item = clipData.getItemAt(0);
            try 
                text = item.getText().toString();

             catch (NullPointerException e) 
                Toast.makeText(MySecretService.this, "exception " + e, Toast.LENGTH_SHORT).show();
            
            Toast.makeText(MySecretService.this, "Text is Copiyed " + text, Toast.LENGTH_SHORT).show();

            //startActivity when copy triggered on text
            startActivity(finalIntent);
        

    );


    return super.onStartCommand(intent, flags, startId);



@Override
public void onDestroy() 
    super.onDestroy();
    // DictionaryActivity.finishAll();
    Toast.makeText(this, "Service is Destroyed !!! ", Toast.LENGTH_SHORT).show();

    //free from memroy
    clipboardManager.removePrimaryClipChangedListener(listener);


【讨论】:

【参考方案3】:

我正在做同样的事情,我注意到只要应用程序缓存在内存中,服务就会运行。我将尝试在服务中添加 if else 语句以检查首选项/设置,以便即使服务正在运行或缓存,它也会检查共享首选项并决定继续或停止。 (保持它检查它是否关闭是不好的,但我想不出别的东西

【讨论】:

【参考方案4】:

您需要从要停止它的位置调用 stopservice(intent) 方法并覆盖服务类中的 onDestroy(),现在 stopservice() 将调用服务类的 destroy 方法现在您可以放置​​代码以断开正在进行的进程onDestroy().

经过这么多努力,我得到了结果!希望你能回答!

【讨论】:

以上是关于无法停止后台服务android的主要内容,如果未能解决你的问题,请参考以下文章

一段时间后,android后台服务停止

Android 退出app,后台推送的服务也停止了,怎么可以做到不停止后台服务呢?

Android服务在其仍处于活动状态时停止后台处理

当应用程序进入后台时停止后台服务

如何让android的service一直在后台运行

当应用程序在后台运行时无法找到位置更新