1

我的应用程序需要知道手机是在口袋里还是在手中,这取决于为个人设置的几个参数,而不是继续执行下一个任务。

我已经阅读了各种博客以及SensorManager android 开发人员,但没有一个帮助我。我在堆栈上找到的唯一相关链接是这个没有解决方案,尽管对该问题的一条评论建议使用Awareness API。我正在经历它,我的理解是用户活动是找到这个的上下文 - 我可能错了。可能有人在这方面工作或正在进行研发,请分享您的观察结果,这可能会以某种方式帮助我走得更远。

有没有办法找到手机是否在口袋里?如果是,有人可以告诉我如何做到这一点吗?

任何指向这些概念的指导/链接都是有帮助的。

谢谢。

4

3 回答 3

1

我在我的项目中实现了这一点。我从光传感器、加速度计和接近传感器获得读数。请记住,它可以大致检测到口袋中是否存在设备。

从传感器(加速度计、接近传感器和光传感器)获取当前参数:

@Override
public void onSensorChanged(SensorEvent event) {

    if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
        g = new float[3];
        g = event.values.clone();

        double norm_Of_g = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]);

        g[0] = (float)(g[0] / norm_Of_g);
        g[1] = (float)(g[1] / norm_Of_g);
        g[2] = (float)(g[2] / norm_Of_g);

        inclination = (int) Math.round(Math.toDegrees(Math.acos(g[2])));
        accReading.setText("XYZ: " + round(g[0]) + ",  " + round(g[1]) + ",  " + round(g[2]) + "  inc: " + inclination);
    }
    if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
        proximityReading.setText("Proximity Sensor Reading:" + String.valueOf(event.values[0]));
        rp = event.values[0];
    }
    if (event.sensor.getType() == Sensor.TYPE_LIGHT) {
        lightReading.setText("LIGHT: " + event.values[0]);
        rl = event.values[0];
    }
    if ((rp != -1) && (rl != -1) && (inclination != -1)) {
        main.detect(rp, rl, g, inclination);
    }
}

然后根据这些数据,我决定设备是否在口袋里:

public void detect(float prox, float light, float g[], int inc){
    if((prox<1)&&(light<2)&&(g[1]<-0.6)&&( (inc>75)||(inc<100))){
        pocket=1;
        //IN POCKET
    }
    if((prox>=1)&&(light>=2)&&(g[1]>=-0.7)){
        if(pocket==1){
            playSound();
            pocket=0;
        }
        //OUT OF POCKET
    }

}

请记住,它并不完全准确。
代码:https
://github.com/IvanLudvig/PocketSword 博客文章:https ://ivanludvig.github.io/blog/2019/06/21/detecting-device-in-a-pocket-android.html

于 2019-06-20T22:50:56.993 回答
1

我们可以稍微接近解决方案的唯一方法是使用。Google Awareness API 无法解决问题,因为它具有完全不同的用法。

  • 光传感器(环境传感器)
  • 接近传感器(位置传感器)

Android 平台提供了四个传感器,可让您监控各种环境属性。您可以使用这些传感器来监控

  • 相对环境湿度
  • 发光
  • 环境压力
  • 环境温度

所有四个环境传感器都是基于硬件的,并且只有在设备制造商将它们内置到设备中时才可用。除了大多数设备制造商用来控制屏幕亮度的光传感器外,环境传感器并不总是在设备上可用。因此,在尝试从环境传感器获取数据之前,在运行时验证环境传感器是否存在尤为重要。

光传感器可用于计算光强度。例如许多具有自动亮度模式功能的手机,此功能适用于光传感器,可根据光强度调整屏幕亮度。有许多单位,如勒克斯、坎德拉、流明等,来测量光强度。

考虑到这一点,当您在口袋里或外口袋里打电话时,光线强度会有很大差异。

尽管在暗室操作手机时也会发生同样的情况。或者在那些光线强度很低的地方。因此,区分这些情况是真正的挑战。您可以结合光传感器使用其他环境传感器来获得有效的结果。但我认为准确的解决方案是冒险的。

要了解有关这些传感器的更多信息,请参阅以下链接

https://developer.android.com/guide/topics/sensors/sensors_environment.html https://developer.android.com/guide/topics/sensors/sensors_position.html

Google 意识 API 不适用于这种情况。as 提供了完全不同的解决方案。 它提供了两个API

  • 围栏 API
  • 快照 API

您可以使用Snapshot API获取有关用户当前环境的信息。使用 Snapshot API,您可以访问各种上下文信号:

  • 检测到的用户活动,例如步行或驾驶。
  • 您已注册的附近信标。
  • 耳机状态(插入与否)
  • 位置,包括纬度和经度。
  • 用户当前所在的位置。
  • 用户当前位置的天气状况。

使用Fence API,您可以根据上下文信号定义栅栏,例如:

  • 用户的当前位置(lat/lng)
  • 用户当前的活动(步行、驾驶等)。
  • 特定于设备的条件,例如是否插入了耳机。
  • 靠近附近的信标。
于 2018-01-30T11:09:53.940 回答
0

对于跨平台解决方案,您现在可以使用NumberEight SDK来完成此任务。

它在 iOS 和 Android 上执行各种上下文识别任务,包括:

  • 实时身体活动检测
  • 设备位置检测(即存在于口袋中)
  • 运动检测
  • 可达性
  • 当地天气

它还可以通过在线门户记录用户上下文以进行报告和分析。

如何检测手机是否在口袋里:

例如,要在 Kotlin 中记录用户活动,您可以:

val ne = NumberEight()

ne.onDevicePositionUpdated { glimpse ->
    if (glimpse.mostProbable.state == State.InPocket) {
        Log.d("MyApp", "Phone is in a pocket!")
    }
}

或在 Java 中:

NumberEight ne = new NumberEight();

ne.onDevicePositionUpdated(
    new NumberEight.SubscriptionCallback<NEDevicePosition>() {
        @Override
        public void onUpdated(@NonNull Glimpse<NEDevicePosition> glimpse) {
            if (glimpse.mostProbable.state == State.InPocket) {
                Log.d("MyApp", "Phone is in a pocket!");
            }
        }
    });

以下是一些iOSAndroid示例项目。

披露:我是开发人员之一。

于 2020-04-27T16:09:57.897 回答