Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/190.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 屏幕锁定3分钟后,onSensorChanged停止调用_Java_Android_Android Studio_Accelerometer - Fatal编程技术网

Java 屏幕锁定3分钟后,onSensorChanged停止调用

Java 屏幕锁定3分钟后,onSensorChanged停止调用,java,android,android-studio,accelerometer,Java,Android,Android Studio,Accelerometer,我正在尝试开发一个简单的应用程序,将用户的活动(加速计值)记录在txt或csv文件中 我的应用程序由两个java类组成MainActivity和MyService。MainActivity包括两个按钮,用于启动和停止服务以及所需的权限。但是,onSensorChanged会在锁定手机(关闭屏幕)后的前3分钟内正常记录,然后停止记录。我一打开屏幕,logd就又开始工作了。txt文件中的记录的行为相同。我发现,如果我忽略电池优化,应用程序似乎工作得很好。不过,我需要手机也在打瞌睡模式下工作,以节省一

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

我的应用程序由两个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();
                }

            }
        }

    }


}
正如你在代码中看到的,我尝试了其他问题的一些建议,比如wakelock和Intent.ACTION\u SCREEN\u关闭,但它们似乎不起作用。

让您的服务保持活力的唯一方法是避免应用程序的电池优化。这在以下两种方式中是可能的请注意在这两种情况下,您都将使设备保持活动状态,这意味着设备将永远不会睡眠(明显地进入睡眠状态)。这就是设备睡眠的全部意义,以避免像您这样的后台服务的未决工作

  • 使用Android
    WakeLock
    s,例如下面的示例

  • 更改设置以避免特定应用程序的电池优化。正如你在问题中提到的
    这是正常的行为。Android删除所有程序以节省电源。如果您想做一项工作,请让用户保持屏幕打开,否则您只能使用AlarmManager呼叫服务(Intent、Reciver)执行“小工作”并再次进入睡眠状态。

    首先感谢您的快速响应。我为GPS值提供了完全相同的服务,即使手机被锁定,它也能正常工作,这就是为什么它在3分钟后停止记录加速度计值对我来说很奇怪的原因。即使安卓系统被锁定,前台服务也不应该运行吗?无论如何,除了使用服务来完成我在打瞌睡模式下想要的任务之外,还有其他可能的方法吗?要支持正常的设备睡眠活动,您需要使用Android API管理后台工作。出于后台目的,他们创建了
    JobSchedular
    WorkManager
    。但请注意,他们会在某个时间段调用您的服务实现一次。例如,每15分钟一次(取决于睡眠的深度)。谢谢您的回答。如上所述,我希望有连续的加速度计记录,以防android被用户移动,否则将有一个无用的电池消耗。例如,如果用户正在睡觉,我不希望有7-8小时的录音,因为他们没有给我重要的信息。我不想让屏幕一直开着,因为这是另一个导致电池耗电的原因。我也尝试过AlarmManager(每30秒发出一次警报)和WakefulBroadcastReceiver,但它们似乎不起作用,因为我不需要“小工作”。还有其他建议吗?我读过这本书。它有很好的相似示例(通过GPS计算距离)
       val wakeLock: PowerManager.WakeLock =
               (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
                   newWakeLock(PowerManager. FULL_WAKE_LOCK, "MyApp::MyWakelockTag").apply {
                    acquire()
                }
            }