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

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(使用前将#替换为@)

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

  • Twitter 登录说明

    我想在 Android 中创建一个 Twitter 应用程序 为此 我想创建一个登录页面并登录到 Twitter 为此 我们需要消费者密钥和消费者密钥 这是什么意思 要创建此登录页面 除了 Twitter 帐户之外 我们还需要其他任何东西吗
  • 在android中通过BLE传输图像

    我使用以下代码传输 1 MB 的图像 如果在每个数据包之间实现线程延迟 则图像将成功传输 如果未设置线程延迟 则所有数据包均从BluetoothGattServer 发送 但BluetoothGattCallback 不会接收所有数据包 任
  • FTS3 在 ORMLite 中搜索?

    我对 FTS3 一无所知 除了http developer android com guide topics search search dialog html http developer android com guide topics
  • 通过 WhatsApp 发送消息

    由于我发现了一些较旧的帖子 表明 Whatsapp 不支持此功能 我想知道是否发生了变化 以及是否有办法打开与我通过意图发送的号码进行 Whatsapp 聊天 UPDATE请参阅https faq whatsapp com en andro
  • Android 如何更改 OnTouchListener 上的按钮背景

    你好 我在 xml 中有一个按钮 我正在使用OnTouchListener在我的活动中获得button按下并释放 但问题是 当我按下按钮时背景颜色没有改变 当我延长可能的活动时OnClickListener背景正在改变 任何人都可以告诉我的
  • 出现错误错误:res/menu/mainMenu.xml:文件名无效:必须仅包含[a-z0-9_。]

    我是安卓新手 刚刚开始使用 我在 res 文件夹中创建了一个文件 menu mainMenu xml 但我得到了错误 Error res menu mainMenu xml invalid file name must contain on
  • Java 文件上传速度非常慢

    我构建了一个小型服务 它从 Android 设备接收图像并将其保存到 Amazon S3 存储桶中 代码非常简单 但是速度非常慢 事情是这样的 public synchronized static Response postCommentP
  • 在旋转时从错误的资源文件夹中提取可绘制对象

    在这里拉我的头发 因此 我正在使用一个具有多种类型的可绘制对象的应用程序 并且它们的结构如下 res Portrait resources drawable mdpi drawable hdpi drawable xhdpi Landsca
  • 在 React Native 中调试应用程序崩溃

    我是 React Native 新手 我正在尝试安装 React Native Facebook SDK 以便我可以使用我的应用程序进行 Facebook 登录 我按照此处列出的步骤操作 https tylermcginnis com in
  • Android 相机未保存在特定文件夹 [MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA]

    当我在 Intent 中使用 MediaStore INTENT ACTION STILL IMAGE CAMERA 时遇到问题 相机正常启动 但它不会将文件保存在我的特定文件夹 photo 中 但是当我使用 MediaStore ACTI
  • react-native run-android 失败并出现错误:任务 ':app:dexDebug' 执行失败

    我使用的是 Windows 8 1 和react native cli 1 0 0 and react native 0 31 0 添加后react native maps对于该项目 我运行了命令react native upgrade并给
  • 如何修改 Skobbler 注释而不重新添加它

    我必须修改 SKAnnotation 的图像 注释生成器代码 private SKAnnotation getAnnotationFromView int id int minZoomLvl View view SKAnnotation a
  • 哪些 Flutter 插件或功能可以利用外部 iOS/Android 显示器来显示与主显示器不同的内容

    我正在构建一个跨平台应用程序 需要在外部显示器上显示不同的视图 通常通过连接到 LCD 投影仪的 HDMI 适配器电缆连接 Flutter 是否能够在内置的外部显示器上显示不同的屏幕 在现有的 Flutter 插件中还是使用现有的 Flut
  • 模块中的类无法加载

    我正在开发一个 2D Unity android 游戏 其中我最近添加了 Firebase Beta SDK 但添加后FirebaseAnalytics unitypackage我面临的错误是 无法加载模块中的类 当我删除文件夹时Fireb
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 在 KitKat 4.4.2 中获取 SDard 路径和大小

    我在 Google Play 上有一个设备信息应用程序 在该应用程序中我有存储信息 我知道 Android 4 4 在访问外部 SD 卡方面发生了一些变化 内部似乎没有给我带来问题 我的问题是 如何可靠地获取 KitKat 上 SD 卡的大
  • Android 中循环事件的星期几和时间选择器

    我想创建一个控件 允许用户在我的 Android 活动中选择一周中的某一天 星期一 和一天中的某个时间 下午 1 00 找不到任何关于此的好帖子 好吧 我想我已经明白了 我只是不喜欢这个解决方案 因为我在一周中的某一天使用的微调器与时间选择
  • 如何在基本活动中使用 ViewBinding 的抽象?

    我正在创建一个基类 以便子级的所有绑定都将设置在基类中 我已经做到了这一点 abstract class BaseActivity2 b AppCompatActivity private var viewBinding B null pr
  • 使用 JobScheduler API 进行位置更新

    下面是我使用 FireBaseJobDispatcher 启动作业的演示代码 public class MainActivity extends AppCompatActivity Override protected void onCre
  • 使用单选按钮更改背景颜色 Android

    我试图通过从单选组中选择单选按钮来更改应用程序选项卡的背景 但是我不确定如何执行此操作 到目前为止我已经 收藏夹 java import android app Activity import android os Bundle publi

随机推荐