gpt4 book ai didi

java - onSensorChanged 在锁定屏幕 3 分钟后停止调用

转载 作者:行者123 更新时间:2023-12-01 22:17:43 25 4
gpt4 key购买 nike

我正在尝试开发一个简单的应用程序,它将在 txt 或 csv 文件中记录用户的 Activity (加速度计值)。

我的应用程序由 2 个 Java 类 MainActivityMyService 组成。 MainActivity 包含两个用于启动和停止服务的按钮以及所需的权限。但是,onSensorChanged 通常会在锁定手机(关闭屏幕)后的前 3 分钟内记录,然后停止记录。一旦我打开屏幕,logd 就会再次开始工作。 txt 文件中的记录具有相同的行为。我发现如果我覆盖电池优化,该应用程序似乎运行良好。但是,我需要手机也以打瞌睡模式工作,以节省电池电量。还有其他人遇到过类似的问题吗?

这是我的前台服务:

public class MyService extends Service implements SensorEventListener {

public static final String CHANNEL_ID = "ForegroundServiceChannel";
private static final String TAG = "MyService";

private Messenger messageHandler;


private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Context mContext;
private PowerManager.WakeLock wakeLock = null;

//private HandlerThread mSensorThread;
//private Handler mHandler;

@SuppressLint("MissingPermission")
@Override
public void onCreate() {
super.onCreate();
Log.v("shake service startup", "registering for shake");
mContext = getApplicationContext();

//mHandler = new Handler(mSensorThread.getLooper());

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer,
SensorManager.SENSOR_DELAY_NORMAL);


PowerManager manager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Wakelock :: TAG");

// Register our receiver for the ACTION_SCREEN_OFF action. This will make our receiver
// code be called whenever the phone enters standby mode.
//IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
//registerReceiver(mReceiver, filter);
}


/*
// BroadcastReceiver for handling ACTION_SCREEN_OFF.
public BroadcastReceiver mReceiver = new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
// Check action just to be on the safe side.
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.v("shake mediator screen off","trying re-registration");
// Unregisters the listener and registers it again.
mSensorManager.unregisterListener(MyService.this);
mSensorManager.registerListener(MyService.this, mAccelerometer,
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
}
}
};
*/

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();

startForeground(1, notification);

return START_STICKY;

//stopSelf();

//return START_NOT_STICKY;
}

private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);

NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}

@Override
public void onDestroy() {
super.onDestroy();
if(mSensorManager != null){
//noinspection MissingPermission
mSensorManager.unregisterListener(MyService.this);
}
//unregisterReceiver(mReceiver);
try{
wakeLock.release();//always release before acquiring for safety just in case
}
catch(Exception e){
//probably already released
Log.e(TAG, e.getMessage());
}

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}



@Override
public void onSensorChanged(SensorEvent event) {
Log.d(TAG, "onSensorChanged: " + event.timestamp + " " + event.values[0] + " " + event.values[1] + " " + event.values[2]);
recordAccelValues(String.valueOf(event.timestamp), event.values[0] + " " + event.values[1] + " " + event.values[2]);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}

private void recordAccelValues(String time, String accel_values) {
String record = time + " " + accel_values + "\n";

String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
if (Build.VERSION.SDK_INT >= 23) {
File sdcard = Environment.getExternalStorageDirectory();
File dir = new File(sdcard.getAbsolutePath() + "/text/");
if(!dir.exists()) {
dir.mkdir();
}
File file = new File(dir, "dailyRecordsAccel.dat");
FileOutputStream os = null;
try {
os = new FileOutputStream(file, true);
os.write(record.getBytes());
os.close();
} catch (IOException e) {
e.printStackTrace();
}

}
}

}


}

正如您在代码中看到的,我尝试了我发现的其他问题中的一些建议,例如唤醒锁和Intent.ACTION_SCREEN_OFF,但它们似乎不起作用。 Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock

最佳答案

保持服务活跃的唯一方法是避免应用程序的电池优化。这可以通过以下两种方式实现。 请注意!在这两种情况下,您都会使设备保持 Activity 状态,这意味着设备永远不会 hibernate (显然会进入打瞌睡状态)。这是设备 sleep 的全部目的,以避免像您这样的后台服务的待处理工作。

  • 使用 Android WakeLock,例如。以下。

   val wakeLock: PowerManager.WakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager. FULL_WAKE_LOCK, "MyApp::MyWakelockTag").apply {
acquire()
}
}
  • 更改设置以避免针对特定应用进行电池优化。正如您在问题中提到的。

关于java - onSensorChanged 在锁定屏幕 3 分钟后停止调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58614272/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com