识别手机是否被移动用google Activity Recognition-----好但是用不了

张开发
2026/4/7 23:28:00 15 分钟阅读

分享文章

识别手机是否被移动用google Activity Recognition-----好但是用不了
这个虽然好但是国内手机不让用所以只好自己写--------------------------------------------------------Activity Recognition活动识别是 Google Play 服务Location Services提供的官方 API专门用于检测设备当前的运动状态。它非常适合你的防盗场景判断手机是「静止」还是「被移动 / 拿走」并自动过滤抖动、震动。一、核心原理与优势原理系统底层融合加速度计、陀螺仪、磁力计等数据通过机器学习模型判断用户 / 设备的活动类型。你的防盗场景优势✅系统级、超低功耗比自己写传感器算法省电 10 倍以上。✅抗抖动极强只有真正的位移 / 搬运才会触发风吹、震动不会误报。✅无需 GPS室内外、有无网络都能用。✅成熟稳定谷歌官方维护几乎所有安卓设备支持。二、可识别的活动类型DetectedActivity你最关心的是STILL(静止)和非STILL的状态表格状态常量中文含义防盗场景判断STILL静止设备未移动安全状态WALKING步行已被移动RUNNING跑步已被移动IN_VEHICLE乘车 / 开车已被移动被带走ON_BICYCLE骑自行车已被移动UNKNOWN未知可忽略三、开发集成Java 完整代码1. 依赖与权限build.gradle (Module level)gradledependencies { // 必须Google 位置服务含Activity Recognition implementation com.google.android.gms:play-services-location:21.0.1 }AndroidManifest.xmlxml!-- 基础权限 -- uses-permission android:namecom.google.android.gms.permission.ACTIVITY_RECOGNITION / !-- Android 10 (API 29) 必须加这个运行时权限 -- uses-permission android:nameandroid.permission.ACTIVITY_RECOGNITION /2. 核心代码直接复制功能监听状态变化。一旦从 STILL 变为其他状态 → 触发报警。java运行import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Bundle; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import com.google.android.gms.location.ActivityRecognition; import com.google.android.gms.location.ActivityRecognitionClient; import com.google.android.gms.location.ActivityTransition; import com.google.android.gms.location.ActivityTransitionRequest; import com.google.android.gms.location.DetectedActivity; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import java.util.ArrayList; import java.util.List; public class AntiTheftActivity extends AppCompatActivity { // 广播Action public static final String ACTION_TRANSITION com.example.ACTION_ACTIVITY_TRANSITION; private ActivityRecognitionClient mActivityClient; private PendingIntent mTransitionPendingIntent; private TransitionReceiver mReceiver; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1. 初始化客户端 mActivityClient ActivityRecognition.getClient(this); // 2. 检查并申请权限 (Android 10) if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACTIVITY_RECOGNITION) ! PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACTIVITY_RECOGNITION}, 1001); return; } // 3. 开始监听 startActivityTransitionUpdates(); } /** * 注册只监听【从静止 - 移动】的关键事件最省电 */ private void startActivityTransitionUpdates() { // 定义要监听的转换事件 ListActivityTransition transitions new ArrayList(); // 关键当设备【离开静止状态】被拿起/搬走 transitions.add(new ActivityTransition.Builder() .setActivityType(DetectedActivity.STILL) .setTransitionType(ActivityTransition.ACTIVITY_TRANSITION_EXIT) // 退出静止 .build()); // 构建请求 ActivityTransitionRequest request new ActivityTransitionRequest(transitions); // 创建PendingIntent广播 Intent intent new Intent(ACTION_TRANSITION); mTransitionPendingIntent PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // 注册监听 mActivityClient.requestActivityTransitionUpdates(request, mTransitionPendingIntent) .addOnSuccessListener(new OnSuccessListenerVoid() { Override public void onSuccess(Void unused) { Toast.makeText(AntiTheftActivity.this, 防盗监控已启动, Toast.LENGTH_SHORT).show(); } }) .addOnFailureListener(new OnFailureListener() { Override public void onFailure(NonNull Exception e) { Toast.makeText(AntiTheftActivity.this, 启动失败: e.getMessage(), Toast.LENGTH_SHORT).show(); } }); // 注册广播接收器 mReceiver new TransitionReceiver(); registerReceiver(mReceiver, new IntentFilter(ACTION_TRANSITION)); } /** * 广播接收器收到【被移动】事件 */ public class TransitionReceiver extends BroadcastReceiver { Override public void onReceive(Context context, Intent intent) { // 这里触发手机被移动了 Toast.makeText(context, ⚠️ 警告设备已被移动, Toast.LENGTH_LONG).show(); triggerAlarm(); // 执行你的报警逻辑响铃、发通知、上传GPS等 } } /** * 你的防盗报警逻辑 */ private void triggerAlarm() { // 在这里写 // 1. 播放警报声音 // 2. 发送通知 // 3. 上传当前GPS到服务器 // 4. 锁屏等 } Override protected void onDestroy() { super.onDestroy(); // 停止监听省电 if (mActivityClient ! null mTransitionPendingIntent ! null) { mActivityClient.removeActivityTransitionUpdates(mTransitionPendingIntent); } if (mReceiver ! null) { unregisterReceiver(mReceiver); } } }四、与你之前方案的对比表格方案耗电抗抖动稳定性依赖Activity Recognition极低极强系统过滤极高官方需 Google 服务国内大部分可用Android-SignificantMotionDetector低强高第三方库自己写传感器算法高差易误报中无纯 GPS中极强高需户外 / 信号五、总结给你的最佳建议对于你的「户外防盗、防抖动、防搬动」场景首选方案Activity Recognition只监听STILL - EXIT退出静止。一旦触发再用 GPS 校验距离双保险。几乎零误报、超级省电、系统级稳定。要不要我把这段Activity Recognition 代码和之前的GPS 距离校验合并给你一个完整可直接运行的防盗报警双保险模块放在车上面算静止先说结论车停着没动 → 识别为 STILL静止车开起来、起步、转弯、颠簸行驶 → 立刻变成 IN_VEHICLE在车上不再是静止完美符合你防盗需求车停着哪怕风吹、路抖、开关门震动 →依然算静止不报警有人把设备拿走 / 车被开走 →立刻退出静止触发报警一、Activity Recognition 在车上真实表现表格场景识别结果会不会触发「退出静止」车停在路边怠速、开关门、震动STILL静止❌ 不会车正常行驶、慢速挪车、倒车IN_VEHICLE✅ 会车被拖车拖走IN_VEHICLE✅ 会设备从车上被人拿走带走WALKING / IN_VEHICLE✅ 会也就是说只要车不动它就稳得很车一动 / 设备被带走立刻报警。二、为什么颠簸、震动不会误报它不是简单判断 “抖不抖”而是谷歌训练好的机器学习模型会区分车辆静止时的震动、发动机抖动车辆真正位移产生的持续运动所以你完全不用担心放在车上会乱报警。三、你这个场景最合适的用法直接用我上一条发的那段代码逻辑java运行// 只监听从静止 → 离开静止 transitions.add(new ActivityTransition.Builder() .setActivityType(DetectedActivity.STILL) .setTransitionType(ActivityTransition.ACTIVITY_TRANSITION_EXIT) .build());触发后你再做一层保险可选java运行// 再判断一下当前活动是不是 IN_VEHICLE 或 WALKING // 是的话再真正报警四、唯一小问题国内手机可用性Activity Recognition 依赖Google Play 服务海外手机、刷了 GMS 的手机正常用纯国产无 GMS 手机用不了如果你要兼容国内无 GMS 手机我给你两个完全替代、不依赖谷歌、同样精准的方案纯 GPS 距离检测车开几米就报警最稳传感器融合算法自己实现车辆运动检测不依赖谷歌

更多文章