Reputation: 27
I wanted to save the sensor data in a text file. But my service can save the data only for few minutes and then stops. I added WakeLock but it does not save the sensor data into the file after few minutes. The activity and service class are-
MainActivity.Class
public class MainActivity extends AppCompatActivity {
private MyService mBoundService;
boolean mIsBound;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((MyService.LocalBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fabric.with(this, new Crashlytics());
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
10);
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
MyService.class
public class MyService extends Service implements SensorEventListener{
SensorManager mSensorManager;
Sensor mAccelerometer;
PowerManager.WakeLock cpuWakeLock;
public class LocalBinder extends Binder{
MyService getService(){
return MyService.this;
}
}
private final IBinder mBinder = new LocalBinder();
private void registerListener() {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
private void unregisterListener() {
mSensorManager.unregisterListener(this);
}
public BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive("+intent+")");
if (!intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
return;
}
Runnable runnable = new Runnable() {
public void run() {
Log.i(TAG, "Runnable executing.");
unregisterListener();
registerListener();
}
};
new Handler().postDelayed(runnable, 500);
}
};
@Override
public void onCreate() {
super.onCreate();
mSensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
PowerManager pm= (PowerManager) getApplicationContext().getSystemService(getApplicationContext().POWER_SERVICE);
cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
unregisterListener();
registerListener();
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
registerListener();
cpuWakeLock.acquire();
return Service.START_STICKY;
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
String entryAcc = System.currentTimeMillis() + ", " + sensorEvent.values[0] + "," + sensorEvent.values[1] + ", " + sensorEvent.values[2] + "\n";
Log.e("String", "value" + entryAcc);
String dataPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyWear_Data/";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm");
Date now = new Date();
String fileName = "acc_" + formatter.format(now) + ".txt";
writeToPath(fileName, entryAcc, dataPath);
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private String writeToPath(String fileName, String data, String path) {
FileOutputStream fos = null;
try {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
File myFile = new File(dir, fileName);
fos = new FileOutputStream(myFile, true);
fos.write(data.getBytes());
fos.close();
Log.e("WriteToFile", "filename : " + fileName);
return myFile.getPath();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
I added wakelock into manifest file also. How can I run the service till my need and save the sensor data to file? I am building the app for android watch which support android 4.2.2.
Upvotes: 0
Views: 1698
Reputation: 1630
Because of the recent changes android will put to sleep every service after a little while in order to preserve battery. The only way to assure the service will run would be to make it run with some kind of foreground UI. Add the following to your Service.
public static final int NOTIFICATION_ID = 1337;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
runAsForeground();
return START_NOT_STICKY;
}
private void runAsForeground() {
Intent notificationIntent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0,
notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this)
.setOngoing(true)
.setSmallIcon(R.drawable.your_icon_here)
.setContentTitle("Service title here")
.setColor(ContextCompat.getColor(this, R.color.white))
.setContentIntent(pendingIntent)
.build();
startForeground(NOTIFICATION_ID, notification);
}
By adding the notification the service will have UI and this will make it with higher priority in front of the OS. Which means that it will be killed only in rare occasions.
Upvotes: 1