Below given code is written to track battery level of device and store it in db. In order to get battery level, function "batterylevel" is called every 3 minutes, and battery level is inserted to db table. And also code saves the time, when device gets full charged, in another db table. Everything works fine for some time. But problem occurs after about 30 minutes, the running service automatically enters to its oncreate method, after that service won't show any logs, eventually service stops causing force close while trying to stop the service manually.
public class BatteryLevelService extends Service {
BroadcastReceiver batteryLevelReceiver;
Timer t ;
Calendar cal;
Date lastBatteryFullTime;
Context context;
int sec;
int lastFullChargeYear,lastFullChargeMonth,lastFullChargeDay;
int lastFullChargeHour,lastFullChargeMinute,lastFullChargeSecond;
private File dir;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
Log.d("Service", "oncreate Service Started");
}
private void batteryLevel() {
cal=Calendar.getInstance();
long currentHour=cal.get(Calendar.HOUR_OF_DAY);
long currentMinute=cal.get(Calendar.MINUTE);
long currentSecond=cal.get(Calendar.SECOND);
final String currentTime=currentHour+" : "+currentMinute+" : "+currentSecond;
Intent batteryIntent = registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int rawlevel = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int level = -1;
if (rawlevel >= 0 && scale > 0) {
level = (rawlevel * 100) / scale;
}
MainActivity.sqladp.insertBatteryLevel(level, currentTime);
if(level==100){
cal=cal.getInstance();
lastFullChargeYear=cal.get(Calendar.YEAR);
lastFullChargeMonth=cal.get(Calendar.MONTH);
lastFullChargeDay=cal.get(Calendar.DAY_OF_MONTH);
lastFullChargeHour=cal.get(Calendar.HOUR_OF_DAY);
lastFullChargeMinute=cal.get(Calendar.MINUTE);
lastFullChargeSecond=cal.get(Calendar.SECOND);
lastBatteryFullTime=new Date(lastFullChargeYear, lastFullChargeMonth, lastFullChargeDay, lastFullChargeHour, lastFullChargeMinute);
String[] lastFullChargeTime=lastBatteryFullTime.toString().split("GMT");
MainActivity.sqladp.deleteLastFullBattery();
MainActivity.sqladp.insertLastUsage("Battery", "", lastFullChargeTime[0], "");
}
Log.d("Battery level", ""+level + "%");
}
#Override
public void onStart(Intent intent, int startId) {
Log.d("Service", "Service Started");
t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Called each time when 1000 milliseconds (1 second) (the period parameter)
batteryLevel();
Log.d("", "batlevel ");
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
3*60*1000);
}
#Override
public void onDestroy() {
Log.d("service", "onDestroy");
t.cancel();
}
The method onStart() is only used for old Android versions (<2.0). For later versions you should use onStartCommand() as bellow:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
this will solve your problem
Related
I have created a Android service where I am finding out the process which are in Error state and the usage stats of app from UsageStatManager. When I run this service then it executes the methods in it once and I want to do a periodic check of the process in error state and the usage stats of apps.
One way I thought of was to implement a while loop with a Thread.sleep() for the time I would like to check my statistics but wondering if there is any other way of doing this in a much better way as placing a while loop may use CPU consumption. Any ideas would be helpfull.
My code:
public class Senddata_1 extends Service {
private String ip = "85.228.204.209";
private int port = 5000;
String message;
String file;
String TAG = "Senddata_1";
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-yyyy HH:mm:ss");
public void find_out_process_in_error_state(){
/*Some code to find out process in error state*/
return;
}
private UsageStatsManager getUsageStatsManager(Context context){
UsageStatsManager usm = (UsageStatsManager) context.getSystemService("usagestats");
return usm;
}
public List<UsageStats> getUsageStatsList(Context context){
List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,startTime,endTime);
return usageStatsList;
}
public void printUsageStats(List<UsageStats> usageStatsList){
}
#Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "Inside service Senddata_1");
find_out_process_in_error_state();
printUsageStats(getUsageStatsList(Senddata_1.this));
new Thread(new Senddata_1.ClientSend()).start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
// return;
}
public class ClientSend implements Runnable {
}
}
you can use Timer and in there set time to start service and run function
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//start service here
}
}, 0, mTimeRate);
mTimeRate will be in milliseconds
I have an App that Monitors room noise levels, I initially got the Code from Github, in the original code, the programmer was monitoring noise levels from Main Activity and displaying the results in textviews, but I want to monitor using a service, I have implemented everything and its working but the textviews seem to be lagging behind, lets say I make a bit of noise and the noise level reach 5, it sticks at 5 even when there is no noise in the room, but in the original app, it was so sensitive that it would go back to 0 or another value depending on the noise levels, I do not know where I have gone wrong but below is my code:
Main Activity
public class StartingPoint extends Activity {
private String volumeBars;
private String volumeLevel;
private TextView volumeBarView;
private TextView volumeLevelView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Toast.makeText(getBaseContext(), "Loading...", Toast.LENGTH_LONG).show();
setContentView(R.layout.activity_starting_point);
//starting Service
startService(new Intent(this, VolumeListerner.class));
volumeBarView = (TextView) findViewById(R.id.volumeBars);
volumeLevelView = (TextView) findViewById(R.id.volumeLevel);
}
#Override
public void onResume() {
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter("UI_UPDATER"));
super.onResume();
// Sound based code
}
#Override
public void onPause() {
super.onPause();
}
public void updateTextView() {
volumeBarView.setText(volumeBars);
volumeLevelView.setText(volumeLevel);
return;
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
volumeBars = intent.getStringExtra("VolumeBars");
volumeLevel = intent.getStringExtra("volumeLevel");
Log.d("receiver", "Got message: " + volumeBars + " : " + volumeLevel);
updateTextView();
}
};
Service:
public class VolumeListerner extends Service {
private static String volumeVisual = "";
private static int volumeToSend;
private Handler handler;
private SoundMeter mSensor;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
/** The service is starting, due to a call to startService() */
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
soundLevelCheck();
return super.onStartCommand(intent, flags, startId);
}
private void soundLevelCheck()
{
mSensor = new SoundMeter();
try {
mSensor.start();
Toast.makeText(getBaseContext(), "Sound sensor initiated.", Toast.LENGTH_SHORT).show();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
// Get the volume from 0 to 255 in 'int'
double volume = 10 * mSensor.getTheAmplitude() / 32768;
volumeToSend = (int) volume;
volumeVisual = "";
for( int i=0; i<volumeToSend; i++){
volumeVisual += "|";
updateUI();
}
handler.postDelayed(this, 250); // amount of delay between every cycle of volume level detection + sending the data out
}
};
// Is this line necessary? --- YES IT IS, or else the loop never runs
// this tells Java to run "r"
handler.postDelayed(r, 250);
}
private void updateUI()
{
Intent intent = new Intent( "UI_UPDATER" );
intent.putExtra("VolumeBars", "Volume Bars: " + String.valueOf(volumeVisual));
intent.putExtra("volumeLevel","Volume Levels: " + String.valueOf(volumeToSend));
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
I recommmand you to use an enhanced event bus with emphasis on Android support. you have a choice between :
1- Otto
2- Event Bus
These methods are implemented in a class extending Service. A new service is started every time a button is pressed.
If the button is pressed once, LogCat outputs what I expect, which includes a final output of "Service onDestroy." However, when the button is pressed twice, the second time before the first service ended, "Service onDestroy." displays only once when the first service is done, and the second service prints out the rest of "Service Running" logs but not "Service onDestroy."
Can anyone tell me why? Thank you!
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i(TAG,"Service onStartCommand " + startId);
final int currentId = startId;
Runnable r = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
long endTime = System.currentTimeMillis() + 10*1000;
while (System.currentTimeMillis() < endTime) {
synchronized(this) {
try {
wait(endTime - System.currentTimeMillis());
}catch (Exception e) {
}
}
}
Log.i(TAG,"Service running");
}
stopSelf();
}
};
Thread t = new Thread(r);
t.start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG,"Service onBind");
return null;
}
#Override
public void onDestroy() {
Log.i(TAG,"Service onDestroy");
}
In the guide for Services they use don't use stopSelf() but stopSelf(startId) when extending Service. The first stopSelf() propably stops both executions of your Service.
See here: http://developer.android.com/guide/components/services.html
Edit: Also a service is only created and destroyed once even when there are several executions of it running it is still a single service. In your case (a Bound Service) it will only be destroyed when the last excecution finishes. For logging every excecution ending you could try to override the stopSelf(int startId) method.
I am trying to create a service with background task. 24 hrs once the thread would start and do the process.
I have tried like this. but its not worked.
public class MyService extends Service {
int counter = 0;
static final int UPDATE_INTERVAL = 10 * 1000; // / 1000 = 1 second
private Timer timer = new Timer();
Home home;
private boolean isRunning = true;
#Override
public IBinder onBind(Intent intent) {
// Not implemented...this sample is only for starting and stopping
// services.
// Service binding will be covered in another tutorial
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Announcement about starting
Toast.makeText(this, "Starting the Demo Service", Toast.LENGTH_SHORT)
.show();
// Start a Background thread
isRunning = true;
// Thread backgroundThread = new Thread(new BackgroundThread());
BackgroundThread();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Background thread
isRunning = false;
// Announcement about stopping
Toast.makeText(this, "Stopping the Demo Service", Toast.LENGTH_SHORT)
.show();
}
private void BackgroundThread() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
String month = String.valueOf(c.get(Calendar.MONTH) + 1);
String year = String.valueOf(c.get(Calendar.YEAR));
String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH));
String months = null;
if (month.startsWith("0") || month.startsWith("1")) {
months = year + "-" + month + "-" + day;
home.loadCalender(months);
} else {
months = year + "-" + "0" + month + "-" + day;
home.loadCalender(months);
}
}
}, 0, UPDATE_INTERVAL);
/*
* counter = 0; while(isRunning) { System.out.println(""+counter++);
* //Thread.currentThread().sleep(5000);
*
* }
*/
System.out.println("Background Thread is finished.........");
}
}
In my main activity, i have started the Service...
plz help me to do this task.
Use AlarmManager to schedule your alarm to occur once per day, using setRepeating() (or perhaps setInexactRepeating(). Please do not waste the user's RAM trying to have a service running all of the time watching the clock tick.
I write an app that schedule to start accelerometer every 15 seconds and run it 10 seconds to retrieve sensor data. I start accelerometer using alarmManager and keep it running with wakelock when screen go off. But I found sometimes:
The accelerometer can't retrieve data after some periods. I mean it have been started according to logcat,but there is not any sensor data,then it is closed and it starts again without data.
I don't know why the accelerometer didn't start any more after some periods and it is fine before. I found logcat says "listener with binder android.os.BinderProxy doesn't exist accelerometer". I don't know why.
following is kernel code:
Activity.java
Intent intent = new Intent(getApplicationContext(),SensorService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long curTime = Calendar.getInstance().getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, curTime, _intervalTime, pendingIntent);
SensorService.java
public void onStart(Intent intent, int startId) {
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
wl.acquire();
Log.d(TAG,"I'm bright!");
try {
Thread.sleep(_delayClose);// kill self after _delayClose ms
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopSelf();// SensorService.this.stopSelf()
}
}).start();
this.mSensorManager.registerListener( _sensorHandle,
accSensor,
sensorDelay)
}
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
this.mSensorManager.unregisterListener(_sensorHandle);
Log.d(TAG,"TIEM UP");
if(wl.isHeld())
{
wl.release();
}
}
I'm guessing that there must be some considerable overhead in registering and unregistering sensor listener that often, plus the alarmManager overhead.
Given that you want sensor data that often, how about just keep your listener registered and have it internally manage when it should and shouldnt do something useful with the samples it's receiving?
public class SensorSamplrActivity extends Activity {
private final static String TAG = "samplr";
private final static int SAMPLE_INTERVAL_SECS = 15;
private final static int SAMPLE_DURATION_SECS = 10;
private SensorManager mSensorManager;
private long whenToStartSample = System.currentTimeMillis();
private long whenToEndSample = System.currentTimeMillis() + SAMPLE_DURATION_SECS;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME);
}
private SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
long now = System.currentTimeMillis();
if (now < whenToStartSample){
// ignore the event & wait for next time to sample
Log.d(TAG,"ignoring events for " + (whenToStartSample - now) + "ms");
return;
}
if (whenToStartSample <= now && whenToEndSample > now){
Log.d(TAG,"Do something with this event # " + now);
}
else {
// we've gone past whenToEndSample so reset timers
whenToStartSample = now + (SAMPLE_INTERVAL_SECS * 1000);
whenToEndSample = whenToStartSample + (SAMPLE_DURATION_SECS * 1000) ;
}
}
};
#Override
public void onDestroy(){
super.onDestroy();
mSensorManager.unregisterListener(mSensorListener);
}
}