Check signal strength mobile timely - android

I need to check my mobile signal strength every 10 secs to send data to server.
I have some data in sqlite. After these 10 seconds gone I send the data.
I have a service with a listener to get the changes on signal. The verification works fine when service start but I can't get signal data throughout the lifecycle. My application has some activities and this service starts in the very beginning.
How can I timely verify the signal in the service and and my data?
public MyService extends IntentService{
public MyService(){
...
telephonyManager = (TelephonyManager) App.getContext().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(
new PhoneStateListener(){
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength){
int signalStrengthPercentage = 0;
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
if(signalStrength != null && gsmSignalStrength != 99){
signalStrengthPercentage = (int) ((float) gsmSignalStrength / 31 * 100);
}
signalIsStrength = signalStrengthPercentage >= 50;
Log.e("ERROR", "Percentage: "+signalStrengthPercentage);
}
}, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
}

Loop this and you will get the result.
long delay = 10000;
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
//your code to verify the signal strength
}
}, delay);

Related

which way is better in android , JobScheduler or use timer?

I'm developing a chat application, For getting new messages in real-time we use a foreground service. (because of some situation we can't use FCM)
To be confident that clients are connected to the server, We send a ping to server every 1 minute with JobScheduler. Now we have a battery usage problem.
It's better to use CountDownTimer like bellow code in our foreground service :
CountDownTimer countDownTimerPingPeriodic;
public static boolean isPinging;
public void pingPeriodic(boolean fromService) {
if (countDownTimerPingPeriodic != null) {
countDownTimerPingPeriodic.cancel();
countDownTimerPingPeriodic = null;
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
long future = 75000;
countDownTimerPingPeriodic =
new CountDownTimer(60000, 60000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
sendPing(false);
pingPeriodic(false);
}
};
isPinging = true;
countDownTimerPingPeriodic.start();
}
});
}
or it's better to use job service like bellow (Now we use bellow code and send ping in onStartJob):
public class ScheduleConnectionJob extends JobService {
private static final String TAG = "ScheduleConnectionJob";
private int i = 0;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public boolean onStartJob(JobParameters params) {
//here I will send a ping to the server
jobFinished(params, true);
Util.scheduleJob(getApplicationContext()); // reschedule the job
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
Util.scheduleJob(getApplicationContext());
return true;
}
#Override
public void onDestroy() {
super.onDestroy();
Util.scheduleJob(getApplicationContext());
}}
And to call and repeat this service We use bellow code to repeat every 1 minute:
public class Util {
public static final long MinimumSchadulePeriodic = 15 * 60 * 1000 ;
// schedule the start of the service every 10 - 30 seconds
public static void scheduleJob(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ComponentName serviceComponent = new ComponentName(context, ScheduleConnectionJob.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
FileLog.i("Util:",
Thread.currentThread().getStackTrace()[2].getLineNumber() + " " +
"scheduleJob:scheduleJob");
builder.setMinimumLatency(MinimumSchadulePeriodic); // wait at least
builder.setOverrideDeadline(60 * 1000); // maximum delay
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); // require unmetered network
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
if (jobScheduler != null) {
jobScheduler.schedule(builder.build());
}
}
}}
You can also use WorkManager if it will be better in your case instead of JobScheduler.
The WorkManager API makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or device restarts.
Checkout this official documentation for further information ::
https://developer.android.com/topic/libraries/architecture/workmanager/
Also read this article https://medium.com/androiddevelopers/introducing-workmanager-2083bcfc4712
If you don't support below SDK 14 you can use workmanager. Otherwise see this guide to read about all the options.
Some extra resources on battery management: Doze and standby, power management restrictions, Analyzing power usage, Excessive wake-ups, Excessive network usage in background
Hope this helps you along a bit. I have to say that having your app ping the backend every minute seems a bit much. Unless its vital that your users receive their messages the instant they get send, it might be better to atleast bump that down to 5 or 10 minutes in background.

Service Is Looping In Crazy Way

I've just made a service to set something, Added a log and a timer, the timer delay is taken form sharedpreferences value, the value is returning 5 minutes, the problem that the Service is looping in a crazy way, it's not a 1 sec delay, nope .. it's less than a second delay and it's outputting the log message .
And to mention, I'm using the same code with another service, I have this problem only in this service, Codes :
Manifest :
<service
android:name=".services.ServiceTest"
android:enabled="true"
android:exported="false" >
</service>
Switch that starts the service :
Intent BroadcastIntent = new Intent(getActivity(),ReceiverTest.class);
BroadcastIntent.setAction(packagetest+"startservice");
getActivity().sendBroadcast(BroadcastIntent);
Receiver takes the action, in a if statement and runs the service via intent in the following way :
Intent ServiceTestIntent = new Intent(context, ServiceTest.class);
context.startService(ServiceTestIntent);
The Service :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences Preference = PreferenceManager.getDefaultSharedPreferences(this);
int Delay= Preference.getInt("Value", 2 * 60 * 1000);
MyTimer = new Timer();
new Thread()
{
public void run() {
MyTimer.schedule(new TimerTask() {
#Override
public void run() {
Log.i(Fragment.TAG,"Message Test");
}
}, Delay, Delay);
}
}.start();
return START_NOT_STICKY;
}
The delay returns 5 minutes (5*60*1000) and then i store it in the sharedpreferences, When i log the value it says 5 minutes, so it's a correct time, even though the default is 2 minutes, the service loops directly and output the message .
Receiver :
if(intent.getAction().equals(mainactivity.package+"startservice"))
{
context.startService(ServiceIntent);
}
UPDATE :
Another thing is, I got 3 other services with different receivers, When i switch any of them, the Test service will be launched, even though i didn't start it or reference it, or anything related to it in the other switches .
I've tried rebooting/App full deletion using Root App remover .
Add a log statement to show the delay. Either the delay value is wrong or the service is being started multiple times:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences Preference = PreferenceManager.getDefaultSharedPreferences(this);
final int Delay= Preference.getInt("Value", 2 * 60 * 1000);
Log.i(Fragment.TAG, String.format("onStartCommand(): delay=%d", Delay));
final Timer MyTimer = new Timer();
new Thread()
{
public void run() {
MyTimer.schedule(new TimerTask() {
#Override
public void run() {
Log.i(Fragment.TAG, "Message Test");
}
}, Delay, Delay);
}
}.start();
return START_NOT_STICKY;
}

TimerTask does not stopped instantly android

I have two services which run periodically based on condition. In once condition the services are run with 5 second timer while in other they run with 10 mins timer.
But when I want to switch from 5 second to 10 mins timer, it does not happen instantly while it runs 4 times extra. I am canceling timer pefectly but does not seems like working..here is code
public final static Handler serviceHandler = new Handler(){
public void handleMessage(Message msg){
if(null != serviceTimer) {
Log.d(TAG, "Coming insisisi");
serviceTimer.cancel();
serviceTimer.purge();
serviceTimer = null;
}
serviceTimer = new Timer();
serviceTimer.scheduleAtFixedRate(new serviceMonitorAcc(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
serviceTimer.scheduleAtFixedRate(new serviceMonitorTrafficStats(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
Log.d(TAG, "TIMER STATTAA"+serviceTimer);
}
};
based on conditions I set the values of variable DELAY_TIMER_TIME and TIMER_START_TIME
private void setTimerInfo(String check){
if(check != null) {
if (check.equals("enable")) {
DELAY_TIMER_TIME = 0;
TIMER_START_TIME = 5000;
} else {
DELAY_TIMER_TIME = 60000;
TIMER_START_TIME = 600000;
}
}
}
the time setting working time only issue is it does not get killed instanlty and start new serviceTimer with new timer setting.
I also tried to kill timertask serviceMonitorAcc and serviceMonitorTrafficStats separatly, but did not work ...any suggestion or pointer for it...

How to implement the timer to run inside Alarm Receiver even after the app quits?

I have used Alarm Service. I have implemented the the alarm to run on every 1 minute. So the broadcast receiver onReceive method gets called even after the app quits. I want to implement a timer inside of this onReceive method. I have to start location tracking and wait for 20 Seconds after that I need to stop the location tracking.
I have tried the below,
TimerTask
Handler
Local Broadcast Receiver
But all the above not capable of running once the app quits.
Inside the alarm receiver I want to implement timer to wait for 20 seconds.
How can I achieve this when the app is in quit state?
My AlaramReceiver onReceive Method:
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
mSharedPrefManager = SharedPrefManager.getInstance(mContext);
mAppUtilInstance.logDebugMessage(TAG, "Track interval alarm receiver.");
// // Check the preference having any current activity
if (mSharedPrefManager.checkForCurrentActivityPref()) {
userActivity = mSharedPrefManager.getCurrentUserActivityPref();
if (mSharedPrefManager.getIsUserMovedPref()) {
// User MOVED
// Call the location service
LocationUpdateTimer locationUpdateTimer = new LocationUpdateTimer(
mContext, userActivity, true);
locationUpdateTimer.initialize();
mSharedPrefManager.setIsUserMovedPref(false);
} else {
// User not MOVED in between the track interval period. He is
// IDLE
// Check whether the location information is returned by the
// google API
if (mSharedPrefManager.checkForLocationEntityPref()
&& mSharedPrefManager.getLocationEntityPref()
.getLatitude().length() > 0) {
// Send the packet information to the Fleetilla server
StoreAndSendLocationInformation storeAndSendLocationInformation = new StoreAndSendLocationInformation(
mContext,
mSharedPrefManager.getLocationEntityPref(),
userActivity);
storeAndSendLocationInformation.storeAndSend();
} else {
// If the location information is not available
mAppUtilInstance
.logDebugMessage(TAG,
"Location information is not generated to store and send.");
}
}
}
}
Location Update Timer Class:
/**
* LocationUpdateTimer Constructor
*/
public LocationUpdateTimer(Context context, String userActivity,
boolean isTosend) {
// Save the context
mContext = context;
mUserCurrentActivity = userActivity;
isToSendLocationInfo = isTosend;
}
/**
* To start the location reporting
*/
private void startLocationReporting() {
if (mLocationProviderStatusListener != null) {
mLocationProviderStatusListener
.requestLocationProvidersToUpdateStatus(mConstants.EMPTY_STRING);
scheduleTimerTask();
}
}
/**
* To schedule the 20 seconds timer task to get the best location
* information and send it to Fleetilla server.
*/
private void scheduleTimerTask() {
bestGPSInfoTimerHandler = new Handler();
bestGPSInfoTimerHandler.postDelayed(bestGPSInfoRunnable,
Constants.TIMER_TASK_DELAY);
mAppUtilInstance.logDebugMessage(TAG,
"20 Sec Location Update TimerTask Scheduled");
}
/**
* To cancel the timer tack which was scheduled for 30sec location update
*/
private void cancelTimerTask() {
if (bestGPSInfoTimerHandler != null) {
mAppUtilInstance.logDebugMessage(TAG, "20 sec TimerTask canceled");
bestGPSInfoTimerHandler.removeCallbacks(bestGPSInfoRunnable);
bestGPSInfoTimerHandler = null;
}
}
/**
* A runnable will be called after the 20 sec time interval
*/
Runnable bestGPSInfoRunnable = new Runnable() {
#Override
public void run() {
// Called after 20 seconds
mAppUtilInstance.logDebugMessage(TAG,
"TimerTask running after 20 sec interval.");
stopLocationReporting();
cancelTimerTask();
if (isToSendLocationInfo) {
// Check whether the location information is returned by the
// google api
if (mSharedPrefManager.checkForLocationEntityPref()
&& mSharedPrefManager.getLocationEntityPref()
.getLatitude().length() > 0) {
// Send the packet information to the server
StoreAndSendLocationInformation storeAndSendLocationInformation = new StoreAndSendLocationInformation(
mContext,
mSharedPrefManager.getLocationEntityPref(),
mUserCurrentActivity);
storeAndSendLocationInformation.storeAndSend();
} else {
// If the location information is not available
mAppUtilInstance
.logDebugMessage(TAG,
"Location information is not generated to store and send.");
mAppUtilInstance
.broadcastStatusMessage(
mContext,
Constants.STATUS_MSG_127
+ "Location information is not generated to store and send.",
Constants.STATUS_CODE_127);
}
}
}
};
Since Android API 11 you can call the goAsync() in onReceive() method. This method returns an object of the PendingResult type. The Android system considers the receiver as alive until you call the PendingResult.finish() on this object. With this option you can trigger asynchronous processing in a receiver. As soon as that thread has completed, its task calls finish() to indicate to the Android system that this component can be recycled.
Here is one Sample Project to demonstrate goAsync() on BroadcastReceiver.
AlarmManager with a PendingIntent works. This is how I do it in one of my apps:
myAlarm = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myNewIntent = new Intent(MyCurrentActivityClass.this, MyNewActivityClass.class);
Calendar wakeUpTime = Calendar.getInstance();
wakeUpTime.add(Calendar.MILLISECOND, (int) myTimeRemaining);
myPendingIntent = PendingIntent.getActivity(MyCurrentActivityClass.this, 0, myNewIntent, 0);
myAlarm.set(AlarmManager.RTC_WAKEUP, wakeUpTime.getTimeInMillis(), myPendingIntent);
You can also put the following in your MyNewActivityClass to wake the device and show through the security screen.
public void onAttachedToWindow() {
//make the activity show even the screen is locked.
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+ WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}

What interval should I use between each WiFi scan on Android?

I need to perform Wifi scans at regular intervals. I am encountering a problem when the time interval is set to 1-2 seconds. It seems like I am not getting any ScanResult. Is there a minimum amount of time to set so that the WifiManager is able to perform a successful WiFi scan?
Here is the code. I am using a Service to do the Wifi scan:
public class WifiScanning extends Service{
private static final String TAG = "WifiScanning";
private Timer timer;
public int refreshRate, numberOfWifiScan, wifiScanGranularity;
WifiReceiver receiverWifi = new WifiReceiver();
WifiManager wifi;
StringBuilder sb;
List<ScanResult> wifiList;
List<APData> apdataList;
List<List<APData>>surveyData;
private TimerTask updateTask = new TimerTask() {
#Override
public void run() {
Log.i(TAG, "Timer task doing work");
wifi.startScan();
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service creating");
//retrieve the mapRefreshRate from config.xml
XMLOperations test = new XMLOperations();
Configuration config = new Configuration();
config = test.saxXmlParsing(this, 1);
if(config==null)
config = test.saxXmlParsing(this, 2);
refreshRate = Integer.parseInt(config.getMapRefreshRate());
numberOfWifiScan = Integer.parseInt(config.getNumberOfWifiScan_Positioning());
wifiScanGranularity = Integer.parseInt(config.getWifiScanGranularity_Positioning());
timer = new Timer();
Log.i(TAG, "Refresh Rate: "+ String.valueOf(refreshRate));
timer.schedule(updateTask, 0, refreshRate);
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
registerReceiver(receiverWifi, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service destroying");
unregisterReceiver(receiverWifi);
if (timer != null){
timer.cancel();
timer.purge();
timer = null;
}
}
class WifiReceiver extends BroadcastReceiver {
public void onReceive(Context c, Intent intent) {
sb = new StringBuilder();
wifiList = wifi.getScanResults();
String ap_ssid;
String ap_mac;
Double ap_rssi;
for(int i = 0; i < wifiList.size(); i++){
ap_ssid = wifiList.get(i).SSID;
ap_mac = wifiList.get(i).BSSID;
ap_rssi = Double.valueOf(wifiList.get(i).level);
APData ap = new APData(ap_ssid,ap_mac,ap_rssi);
apdataList.add(ap);
sb.append(" " + (wifiList.get(i).SSID).toString());
sb.append(" " + (wifiList.get(i).BSSID).toString());
sb.append((" " + String.valueOf(wifiList.get(i).level)));
sb.append("\n");
}
Log.d(TAG, sb.toString());
for(int i=1; i<=numberOfWifiScan; i++){
surveyData.add(apdataList);
}
}
}
}
However, I seem to get Nullpointer at this line: apdataList.add(ap);. So I wonder whether the interval is too short, which causes ScanResult to be empty?
EDIT after you posted your code:
apdataList does not seem to be initialized in onCreate()
add this to onCreate():
apdataList = new List<APData>();
Minimum scanning delay
I think that there is no absolute minimum scanning delay. It depends too much on the hardware performances.
My advice is that you add a 'As Fast As Possible' option to your preferences then use an asynchronous loop that relaunch a scan as soon as new results are found (see the code snippet below, it was updated to suit your needs). This way, it will only be limited by hardware performances.
Also you can poll the ScanResults using WifiManager.getScanResults() The recommended way is to launch WifiManager.startScan() and set up a BroadcastReceiver for WifiManager.SCAN_RESULTS_AVAILABLE_ACTION to be notified as soon as the scan results are ready.
Here's a sample code (borrowed from here and adapted to your needs):
IntentFilter i = new IntentFilter();
i.addAction (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
registerReceiver(new BroadcastReceiver(){
public void onReceive(Context c, Intent i){
// Code to execute when SCAN_RESULTS_AVAILABLE_ACTION event occurs
WifiManager w = (WifiManager) c.getApplicationContext().getSystemService(Context.WIFI_SERVICE); //Use getApplicationContext to prevent memory leak
myScanResultHandler(w.getScanResults()); // your method to handle Scan results
if (ScanAsFastAsPossible) w.startScan(); // relaunch scan immediately
else { /* Schedule the scan to be run later here */}
}
}, i );
// Launch wifiscanner the first time here (it will call the broadcast receiver above)
WifiManager wm = (WifiManager)getApplicationContext.getSystemService(Context.WIFI_SERVICE);
boolean a = wm.startScan();
From Android 8 and higher, the limit is 4 times in 2 minutes.
So you could scan 4 times with 1 second of delay in between. But you would not get any further scan results for the next 126 seconds.
So the fastest interval where every scan is successful would be every 30 seconds.

Categories

Resources