利用系统自带的API判断应用程序是否在后台运行

本文介绍了一种优雅地检测Android应用前后台状态变化的方法,避免了遍历进程信息的低效方式。通过自定义Application并实现ActivityLifecycleCallbacks接口,利用计数器策略精准判断应用状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般情况下判断app是否在后台运行主要通过系统服务Context.ACTIVITY_SERVICE获取activityManager,然后再通过遍历当前应用的进程信息来判断是否在后台运行,比如如下方法:

public static boolean isBackground(Context context) {  
        ActivityManager activityManager = (ActivityManager) context  
                .getSystemService(Context.ACTIVITY_SERVICE);  
        List<RunningAppProcessInfo> appProcesses = activityManager  
                .getRunningAppProcesses();  
        for (RunningAppProcessInfo appProcess : appProcesses) {  
            if (appProcess.processName.equals(context.getPackageName())) {  
               
                if (appProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {  
                         return true;  //处于后台
                } else {  
                  
                    return false;  //处于前台
                }  
            }  
        }  
        return false;  
    }  

这种方法也是比较通用的方法,但是有一个缺点,就是效率可能会差一些,因为要遍历进程信息。

如果想要用优雅一些的方式来处理的话也是可以的,我们可以利用Google提供的另外一个api来实现。Android sdk 14版本开始,官方提供了一个回调:ActivityLifecycleCallbacks,利用这个回调可以检测到应用内所有activity的生命周期,因为这个回调本身定义了activity的所有生命周期方法!

public interface ActivityLifecycleCallbacks {
        void onActivityCreated(Activity activity, Bundle savedInstanceState);
        void onActivityStarted(Activity activity);
        void onActivityResumed(Activity activity);
        void onActivityPaused(Activity activity);
        void onActivityStopped(Activity activity);
        void onActivitySaveInstanceState(Activity activity, Bundle outState);
        void onActivityDestroyed(Activity activity);
    }

那么如何使用这个回调实现上文讲到的前后台切换的监听处理呢?

需要说明的是,ActivityLifecycleCallbacks回调的注册和监听都需要在自定义的application中进行,所以需要预先自定义一个application。

首先定义一个计数器count=0;至于为甚么要使用计数器,后续会有说明

oncreate方法中调用registerActivityLifecycleCallbacks()方法注册回调,代码如下:

this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                

            }

            @Override
            public void onActivityResumed(Activity activity) {

            }

            @Override
            public void onActivityPaused(Activity activity) {
//                Toast.makeText(activity,"应用程序进入后台",Toast.LENGTH_LONG).show();
            }

            @Override
            public void onActivityStopped(Activity activity) {
                
                

            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });

然后重写onActivityStarted和onActivityStopped,在onActivityStarted中让计数器+1;在onActivityStopped中让计数器-1;

onActivityStopped中判断计数器是否=0,如果计数器==0,说明程序运行在后台。代码如下

@Override
public void onActivityStarted(Activity activity) {
       count+=1;

}
@Override
public void onActivityStopped(Activity activity) {
       count-=1;
       if(count==0){
           Toast toast=Toast.makeText(activity,"",Toast.LENGTH_LONG);
           toast.setText("应用程序进入后台");
           toast.show();//这种方式的toast可以去掉默认的前缀
          }
}

之所以要定义计数器并且有一个加减的操作是因为,如果只是单纯使用两个生命周期方法判断的话会出现问题。比如两个AB页面之间跳转,如果不用计时器判断,就会出现A跳转到B之后也会有toast提示的现象,因为A页面跳转到B页面的时候会执行onActivityStopped方法。

### 微信小程序前后端分离开发:前端原生实现与后端Tp8.0框架对接 #### 前言 微信小程序是一种轻量级的应用形式,适合构建跨平台的移动应用。在实际项目中,通常采用前后端分离的方式进行开发。以下是对如何使用微信小程序原生开发前端并与基于ThinkPHP 8.0 (简称Tp8.0) 搭建的后端进行交互的技术解析。 --- #### 小程序前端开发准备 1. **开发环境安装** 开发者需先安装官方推荐的小程序编译工具HBuildX[^2],并配合微信开发者工具完成调试工作。确保微信开发者工具的基础库版本不低于`2.8.3`,以支持最新的API功能[^2]。 2. **目录结构说明** 微信小程序的标准文件夹结构如下: ```plaintext project/ ├── app.js // 应用逻辑入口 ├── app.json // 全局配置文件 ├── app.wxss // 全局样式表 └── pages/ // 页面目录 ├── index/ // 首页页面 ├── index.js // 脚本逻辑 ├── index.wxml // 结构模板 ├── index.wxss // 样式定义 ``` 3. **网络请求封装** 使用`wx.request()`方法发起HTTP请求,建议通过封装统一处理接口调用中的公共参数(如Token)、错误码判断等功能。 ```javascript function request(url, method = 'GET', data = {}) { return new Promise((resolve, reject) => { wx.request({ url, method, data, header: { 'Content-Type': 'application/json' }, success(res) { if (res.statusCode === 200 && res.data.code === 0) { resolve(res.data); } else { reject(res.errMsg || '服务器返回异常'); } }, fail(err) { reject(err.errMsg); } }); }); } module.exports = { get: (url, data) => request(url, 'GET', data), post: (url, data) => request(url, 'POST', data) }; ``` --- #### Tp8.0后端服务搭建 1. **创建控制器** 在Tp8.0框架下新建一个用于接收小程序请求的控制器,例如`Api.php`。 ```php namespace app\controller; use think\Controller; use think\Request; class Api extends Controller { public function getUserInfo(Request $request) { $data = $request->param(); if (!isset($data['openid'])) { return json(['code' => -1, 'msg' => '缺少必要参数']); } // 查询数据库获取用户信息... $userInfo = [ 'name' => '张三', 'age' => 25 ]; return json(['code' => 0, 'data' => $userInfo]); } } ``` 2. **路由配置** 定义RESTful风格的路由规则以便于小程序访问对应的接口资源。 ```php use think\facade\Route; Route::get('api/user/:id', 'Api/getUserInfo'); // 获取指定ID用户的详情 Route::post('api/login', 'Api/doLogin'); // 用户登录接口 ``` 3. **数据校验与安全防护** 对外部传入的数据实施严格的合法性检验机制,防止SQL注入等攻击行为发生。可以利用Tp8自带验证器类来简化此过程。 --- #### 数据传输协议设计 - **JSON格式通信** 双方约定好固定的响应包体结构,便于客户端快速定位业务状态及有效载荷部分。 ```json { "code": 0, // 错误编码,成功时为0 "message": "", // 提示文字描述 "result": {} // 实际携带的结果集对象或者数组 } ``` - **身份认证方案** 推荐引入JWT(JSON Web Token),既方便又高效地解决无状态会话管理难题。每次从小程序发出请求前附加Authorization头部字段即可表明当前使用者的身份标识。 --- #### 示例场景演示——用户登录流程 ##### 步骤一:唤起微信授权弹窗 ```javascript // 登录按钮绑定事件处理器 bindGetPhoneNumber(e) { const encryptedData = e.detail.encryptedData; const iv = e.detail.iv; this.loginWithPhone({ encryptedData, iv }); } loginWithPhone(data) { const that = this; wx.cloud.callFunction({ name: 'decryptPhoneNumber', data, success(res) { console.log('解密后的手机号:', res.result.phoneNumber); // 向TP8 API提交号码换取token that.postToServer('/api/auth/register_by_phone', { phone: res.result.phoneNumber }) .then(response => { wx.setStorageSync('jwt_token', response.token); // 缓存到本地存储空间里头去 }).catch(error => {}); } }); } ``` ##### 步骤二:后端解析加密资料生成令牌 ```php public function registerByPhone($params){ try{ $decryptedNumber = decryptWeixinEncryptedString($params['session_key'], $params['iv'], $params['encrypted_data']); // 存储新注册记录至DB... return ['status'=>'success','token'=>generateJwtForUser($userId)]; } catch (\Exception $e){ throw new \RuntimeException("无法完成电话登记:".$e->getMessage()); } } ``` --- #### 注意事项 - 确保HTTPS启用状态下运行生产模式下的站点链接地址; - 测试期间允许任意IP来源连接测试服但上线之前务必限定白名单范围内的合法域名才可正常访问敏感操作接口; ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值