【问题标题】:Can't stop background service android无法停止后台服务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");
        }

任何想法如何阻止它?

【问题讨论】:

  • 你怎么知道它没有停止?

标签: java android android-intent android-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().

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-11
        • 2020-08-09
        • 1970-01-01
        • 2011-05-06
        相关资源
        最近更新 更多