当活动从最近的活动中删除时,优雅地清理绑定服务

2024-04-29

我有一个绑定服务,需要时会转到前台。
这是我所拥有的简化版本:

class MyService extends Service {
    private static final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder serviceBinder) {
            instance.bound();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            instance.unbound();
        }
    };
    private static MyService instance;

    public MyService() {
        instance = this;
    }

    public static boolean bind(final Context context) {
        final Intent intent = new Intent(context, MyService.class);
        return context.bindService(intent, MyService.serviceConnection, Context.BIND_AUTO_CREATE);
    }

    public static void unbind(final Context context) {
        context.unbindService(MyService.serviceConnection);
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        // not being called
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // not being called
    }

    private void bound() {}

    private void unbound() {
        // not being called
    }
}

然后在我的活动中我只需这样做来绑定:

MyService.bind(this);

这是解除绑定:

MyService.unbind(this);

问题是,我似乎无法知道用户何时将活动从最近的活动中删除。

这是我尝试过的:

  1. 使用活动onDestroy方法:不,没有被调用
  2. 使用活动onPause/onStop方法:无法真正区分滑动大小写和仅进入后台,因为isFinishing()结果是false在所有情况下。
  3. 使用服务onTaskRemoved or onUnbind方法:不被调用
  4. In my AndroidManifest.xml adding android:stopWithTask="true"在服务元素中:当活动被滑动时,这确实会终止我的服务,but结果是:MyActivity has leaked ServiceConnection。不太清楚为什么,但我的猜测是我没有机会打电话给unbindService().

我做错了什么或者我错过了什么?
Thanks.


正如 mklimek 已经提到的,onTaskRemoved()这是实现这一目标的方法。

我在一个具有由活动启动和绑定的绑定服务的项目中使用它。以下是各个部分(为了安全起见,我将添加一些上下文):

Activity调用自定义startService() and bindService()辅助方法来自onCreate():

private void startService() {
    Intent myServiceIntent = new Intent(this, packageName.MyService.class);
    startService(myServiceIntent);
}

private void bindService() {
    mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mService = MyServiceListener.Stub.asInterface(iBinder);

            try {
                mService.registerCallback(myServiceCallback);
                mService.doSomething();
            } catch (RemoteException e) {
                MLog.w(TAG, "Exception on callback registration; Service has probably crashed.");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mService = null;
        }
   };

    if(!myServiceIsBound) {
        Intent myServiceIntent = new Intent(this, packageName.MyService.class);
        bindService(myServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
        myServiceIsBound = true;
        // service is now bound
    } else {
        // service has already been bound
    }

}

现在,到Service类别: 在它的onCreate(),我显示一条通知(据悉这是运行后台服务所需的)并设置 Binder:

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

    // Setup Binder for IPC
    mBinder = new MyServiceBinder();

    mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

    [...display notification code...] 
}

服务接口(告诉我这是否有趣,否则我就把它留在这里):

private class MyServiceBinder extends MyServiceListener.Stub {

    @Override
    public void registerCallback(MyServiceCallback callback) throws RemoteException {
         [...]
    }

    // further methods for the service interface...
}

My onTaskRemoved()其他生命周期方法如下所示:

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);

    // do something adequate here
}


// Lifecycle management
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_REDELIVER_INTENT;
}


// Binding
@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
    return super.onUnbind(intent);
}

My onTaskRemoved()每次我从最近的应用程序列表中滑动活动时都会调用。你确定你的onTaskRemoved()未调用方法(您是否在其中放置了一些日志记录代码)?另请务必致电super.onTaskRemoved()里面的方法。

我们的代码看起来非常相似,只是我将 ServiceConnection 设置和服务绑定代码放入了 Activity 中。您将很多此类逻辑移至服务本身中。

我只能猜测,也许这里存在服务连接泄漏的问题,因为您的 ServiceConnection 是 Service 类的静态成员,并且您在 ServiceConnection 中维护对服务的引用(通过您的“实例”变量) 。我不确定,但当活动终止时,两个链接似乎都没有损坏。请注意,在我的代码中,ServiceConnection 是如何成为 Activity 的成员,并且我清除了对的引用mService in onServiceDisconnected()为了安全起见。也许您可以稍微重构一下,考虑到 Activity 终止时无法进行 GC 的引用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当活动从最近的活动中删除时,优雅地清理绑定服务 的相关文章

  • Android TelecomManager 中的 addIncomingCall 没有执行任何操作

    我正在尝试使用本机 Android 来电 UI 我有一个连接服务 并且我已经成功注册了一个电话帐户 但在我调用方法 addNewIncomingCall 后什么也没有发生 对我所缺少的有什么想法吗 显现
  • 如何访问 Android 心率传感器原始数据? (反射光,不是心跳)

    心率传感器上的 android sdk 仅返回计算出的 bpm 我对此不感兴趣 我需要访问 Android 心率传感器原始数据 例如就反射值的强度而言将会很大 因为心率传感器基本上使用 LED 并测量随时间变化的反射率 如果可能 访问由任何
  • 通过代码在创建时突出显示 ListView 项目

    我想在创建 listView 时突出显示 ListView 的第一行 0 我尝试了不同的方法 就像您在注释代码中看到的那样 但没有任何效果 这很奇怪 因为 OnItemClickListener 中的突出显示工作正常 它通过 xml 选择器
  • Android:如何暂停和恢复可运行线程?

    我正在使用 postDelayed 可运行线程 当我按下按钮时 我需要暂停并恢复该线程 请任何人帮助我 这是我的主题 protected void animation music6 music4 postDelayed new Runnab
  • 嵌套 XML 布局文件

    android 有没有办法从另一个布局文件引用 xml 布局文件 为了更好地解释 我有一个名为layout1 xml 和layout2 xml 的布局文件 我可以从layout1 xml引用layout2 xml吗 用这个
  • 如何在不使用 Firebase 控制台的情况下发送 Firebase 云消息通知?

    我从新的 Google 通知服务开始 Firebase Cloud Messaging 感谢这段代码https github com firebase quickstart android tree master messaging htt
  • 自动删除 Firebase 通知

    我有一个问题 我都读过让通知在 5 分钟后消失 https stackoverflow com questions 15648699 make notification disappear after 5 minutes and 几秒钟后清
  • 什么是 Android 测试协调器?

    谷歌最近发布了Android测试支持库1 0 读完后overview https android developers googleblog com 2017 07 android testing support library 10 is
  • 如何在android中的谷歌地图上聚焦标记

    我只是想知道我们是否可以关注 Android 应用程序中添加的标记 如果是 怎么办 或者有没有其他方法可以完成这项任务 可以说我使用下面的代码添加了一个标记 map addMarker new MarkerOptions title tit
  • Android - 状态栏阻止全屏

    我的应用程序启动时可以全屏正确运行 然而 在最小化然后返回应用程序后 状态栏会弹出 并将我的视图向下推一点 如何防止状态栏移动我的视图 这是我的布局
  • 使用 Proguard 通过 Dropbox.com 库混淆 Android 应用程序

    我刚刚创建了一个需要 Dropbox com API 库的 Android 应用程序 我现在尝试在 发布 模式下构建应用程序 并希望在代码上运行混淆器以对其进行混淆 但是 每当我尝试运行 Proguard 时 都会收到以下错误 Progua
  • Android - 存储对ApplicationContext的引用

    我有一个静态 Preferences 类 其中包含一些应用程序首选项和类似的内容 可以在那里存储对 ApplicationContext 的引用吗 我需要该引用 以便我可以在不继承 Activity 的类中获取缓存文件夹和类似内容 你使用的
  • 如何将 JSON 数据从 Android 发送到 php url?

    我想将登录信息从我的应用程序发送到 php url 因为这我的应用程序将崩溃 任何人都可以帮助我解决这个问题 这是我的服务器登录方法 我想将数据发送到此登录方法 Method public method login Parameters 3
  • Android 的 Intent 和 Parcelable 对象

    为什么我需要打包我的对象 即使我只需将其发送到同一任务的另一个线程 实际上 我需要打开一个甚至可以在同一线程 主线程 上运行的活动 换句话说 为什么 Google 不提供一个 startActivity 版本 它采用通用对象广告参数而不是捆
  • 以 HTML 格式发送电子邮件

    我想发送 HTML 格式的电子邮件 如下图所示 我怎样才能做到这一点 请帮我 提前致谢 String body new String table tr td br header td tr br br Get b Best Score b
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • onPrepareOptionsMenu 复制 ActionBar 中的项目

    当我使用 onPrepareOptionsMenu 添加菜单项时 该菜单项会在操作栏中复制其自身 我正在使用片段并在主要活动的 ActionBar 中创建初始菜单 如下所示 Override public boolean onCreateO
  • 调试android数据绑定?

    谁能告诉我如何调试或找到数据绑定生成的代码 从this https www youtube com watch v NBbeQMOcnZ0链接我发现它生成了所需的代码 我猜您正在寻找自动生成的绑定 java 文件 我也在寻找他们 最后我在这
  • TabLayout 的不同 tabMode

    我正在使用 ViewPager 和 TabLayout 如果选项卡可以放置在显示 tabMode 上 则它们必须是 app tabMode fixed else app tabMode scrollable 我怎样才能做到这一点 我不明白你
  • 在数组列表中过滤 Filterable 不取消之前的过滤

    我看过过滤器方法文档 其中显示调用过滤器会取消所有先前未执行的过滤请求 并发布一个稍后将执行的新过滤请求 但我收到的实际回调有些不同 在我的实现中 它不会取消先前的过滤器请求并调用publishResults 最近一次搜索条件后的上一次搜索

随机推荐