I'm taking the google calendar API data for my mobile application. i want to check the time to time the changes of the calendar. For that i know, i have to used a thread.
if (isChecked) {
Runnable runnable = new Runnable() {
public void run() {
long endTime = System.currentTimeMillis() + 1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
getResultsFromApi();
} catch (Exception e) {}
}
}
}
};
Thread mythread = new Thread(runnable);
mythread.start();
Toast.makeText(AlertActivity.this, "Calendar Settings Enabled",
Toast.LENGTH_SHORT).show();
} else {
// The toggle is disabled
for(int i=0;i<=broadcastCodeCal;i++)
cancel_Alarm(i);
Toast.makeText(AlertActivity.this, "Calendar Settings Disabled",
Toast.LENGTH_SHORT).show();
}
I want to know how to check the calendar details changes time time to through the mobile application... please guide me...
Create a JobScheduler as below
public static void scheduleJob(Context context) {
ComponentName serviceComponent = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setMinimumLatency(1 * 1000); // wait at least
builder.setOverrideDeadline(3 * 1000); // maximum delay
JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
jobScheduler.schedule(builder.build());
}
Create the following receiver
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Util.scheduleJob(context);
}
}
Register the receiver in the Android manifest for the BOOT_COMPLETED event.
<receiver android:name="MyStartServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Create a JobService and add your existing code in to onStartJob
public class TestJobService extends JobService {
private static final String TAG = "SyncService";
#Override
public boolean onStartJob(JobParameters params) {
Intent service = new Intent(getApplicationContext(), LocalWordService.class);
getApplicationContext().startService(service);
Util.scheduleJob(getApplicationContext()); // reschedule the job
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return true;
}
}
For more details refer : linkhere
Related
In my application I want to get GPS location of through a foregrond service and receiver. every thing is running fine but after two or three successful run. service is not able to detect internet and returns false
here is the code
Code for receiver of calling service in activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent ll24 = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent recurringLl24 = PendingIntent.getBroadcast(getBaseContext(), 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP,0, 30*10*100, recurringLl24);
}
//.....
}
& in receiver class
public class AlarmReceiver extends WakefulBroadcastReceiver
{
static Context context;
Date curTime,sdf,edf;
private static final String LOG_TAG = "ForegroundService";
#Override
public void onReceive(Context context, Intent intent)
{
try
{
Calendar c = Calendar.getInstance();
curTime = new SimpleDateFormat( "HH:mm" ).parse(c.get( Calendar.HOUR_OF_DAY)+":"+c.get( Calendar.MINUTE));
sdf = new SimpleDateFormat( "HH:mm" ).parse("08:00");
edf = new SimpleDateFormat( "HH:mm" ).parse("20:00");
if(curTime.after(sdf) && curTime.before(edf))
{
Intent ll24Service = new Intent(context, ForegroundService.class);
ll24Service.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
ForegroundService.IS_SERVICE_RUNNING = true;
startWakefulService(context,ll24Service);
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
in service class
public class ForegroundService extends Service
{
...
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
AlarmReceiver.completeWakefulIntent(intent);
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION))
{
Log.i(LOG_TAG, "Received Start Foreground Intent ");
showNotification();
Calendar c = Calendar.getInstance();
curDateTime = c.get( Calendar.YEAR)+"-"+ String.valueOf(c.get( Calendar.MONTH )+1)+"-"+ c.get( Calendar.DAY_OF_MONTH)+" "+c.get( Calendar.HOUR_OF_DAY)+":"+c.get( Calendar.MINUTE)+":"+c.get( Calendar.SECOND);
gps = new GPS(ForegroundService.this);
if(gps.canGetLocation())
{
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
latt=Double.toString(latitude);
longi =String.valueOf(longitude);
insertData();
}
else
{
gps.showSettingsAlert();
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroy");
}
private void insertData()
{
try
{
String QUERY = "insert into GpsLoc values('"+usr+"','"+latt+"','"+longi+"','"+curDateTime+"')";
myDatabase.execSQL(QUERY);
Log.i(LOG_TAG, "insert");
ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
Boolean isInternetPresent = cd.isConnectingToInternet();
if(isInternetPresent)
{
Log.i(LOG_TAG, "chk int");
addToJason();
}
else
{
Log.i(LOG_TAG, "No int");
stopForeground(true);
stopSelf();
}
}
catch(Exception ex)
{
Toast.makeText(getApplicationContext(), "Data not inserted : "+ex.toString(), Toast.LENGTH_LONG).show();
}
}
Every thing is running fine as shown in the log:
03-19 12:11:48.160: I/ForegroundService(17476): Received Start
Foreground Intent
03-19 12:11:48.270: D/Network(17476): Network
03-19 12:11:48.340: I/ForegroundService(17476): insert
03-19 12:11:48.390: I/ForegroundService(17476): chk int
03-19 12:11:49.340: I/ForegroundService(17476): uploaded
03-19 12:11:49.350: I/ForegroundService(17476): In onDestroy
But after two or three run same log became
03-19 12:15:34.670: I/ForegroundService(17476): Received Start Foreground Intent
03-19 12:15:34.740: D/Network(17476): Network
03-19 12:15:34.780: I/ForegroundService(17476): insert
03-19 12:15:34.780: I/ForegroundService(17476): No int
03-19 12:15:34.850: I/ForegroundService(17476): In onDestroy
the problem is at checking internet connection while app is not running and it is called through service. Please suggest any solution
Some times it throuws :
03-27 12:30:07.240: I/ForegroundService(1543):
android.view.WindowManager$BadTokenException: Unable to add window --
token null is not for an application
and some times : Error converting result jsonobject
Please help Problem Strat Here when we called to detect internet in service
ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
Boolean isInternetPresent = cd.isConnectingToInternet();
Add this dependency in your gradle file.
compile 'com.firebase:firebase-jobdispatcher:0.8.5'
Create a Firebase JobService File and declare in manifest.
<service
android:exported="false"
android:name="._User_Classes.User_Call_Record.ScheduledJobService">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>
</service>
Declare and start the JobService from your activity or fragment
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(ScheduledJobService.class) // the JobService that will be called
.setRecurring(false) //repeat the job or not
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setTrigger(Trigger.executionWindow(0, 60))
.setLifetime(Lifetime.FOREVER)
.setTag("demo") // uniquely identifies the job
.build();
dispatcher.mustSchedule(myJob);
Below is the JobService class which will be called each time the job is executed.
public class ScheduledJobService extends JobService {
#Override
public boolean onStartJob(JobParameters job) {
if(isConnected(this))
{
//internet available
}
else{
//internet not available
}
//perform your operations
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new
GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(ScheduledJobService.class) // the JobService that will be called
.setRecurring(false) //repeat the job or not
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setTrigger(Trigger.executionWindow(0, 60))
.setLifetime(Lifetime.FOREVER)
.setTag("demo") // uniquely identifies the job
.build();
dispatcher.mustSchedule(myJob);
return true;
}
#Override
public boolean onStopJob(JobParameters job) {
return false;
}
public static NetworkInfo getNetworkInfo(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo();
}
/**
* Check if there is any connectivity
*
* #param context
* #return
*/
public static boolean isConnected(Context context) {
NetworkInfo info = getNetworkInfo(context);
return (info != null && info.isConnected());
}
}
I hope it helps
I'm using jobscheduler since it's no longer possible to declare a network connectivity intent in manifest. I've tried using .setPeriodic(10 * 1000) to make the job periodic but in doing so, the job runs after 10 seconds even if there is no available network as if it is ignoring this line .setRequiredNetworkType(NETWORK_TYPE_ANY)
And if I remove .setPeriodic(10 * 1000) then the job runs only once. What I want to achieve is the same that was possible before the background optimisation and disabling apps from waking based on a connectivity change: If there is an available network then run the jobservice, if there is none do nothing.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main5);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
JobScheduler mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = null;
builder = new JobInfo.Builder(1, new ComponentName(getPackageName(),
MyJobService.class.getName()))
.setRequiredNetworkType(NETWORK_TYPE_ANY)
.setPeriodic(10 * 1000);
if (mJobScheduler.schedule(builder.build()) <= 0) {
Log.e("gch", "can't Schedule job for MyJobService");
} else {
Log.d("gch", "Schedule job for MyJobService");
}
}
}
and this is the jobService
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyJobService extends android.app.job.JobService {
public MyJobService() {
}
#Override
public boolean onStartJob(JobParameters jobParameters) {
Log.e("gch", "onStartJob");
Toast.makeText(this, "onStartJob", Toast.LENGTH_SHORT).show();
Intent inent = new Intent(this, AnotherActivity.class);
inent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(inent);
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
Log.e("gch", "onStartonStopJob");
Toast.makeText(this, "onStartonStopJob", Toast.LENGTH_SHORT).show();
return true;
}
}
I've added this to the manifest
<service
android:name=".MyJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
I create a static Handler to change some UI texts and plots in an activity. There is a timer created in a bluetooth service. Every second it will check the database for last message and update the time. For example, message comes in 1 second ago 2 seconds ago 3 seconds ago... I store the time when last message came in as yyyy/mm/dd hh:mm:ss a java Date long value.
My problem is at a line where "if (HomeActivity.mHandler != null) {" in the service class below, it gives an error "Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()". This happens when I shut down and restart the phone. The ACTION_BOOT_COMPLETED is catch and trying to run that code, then it throws exception. Does anyone know how to fix it?
Here is my codes:
Activity:
public class HomeActivity extends Activity {
public static Handler mHandler = new Handler() {
public void handleMessage(final Message msg) {
super.handleMessage(msg);
final Bundle bundle = msg.getData();
...
}
};
}
Service:
public class BluetoothLeService extends Service {
#Override
public void onCreate() {
// doing some other bluetooth stuffs here
...
int ONE_SECOND = 1*1000;
Timer updateTimer = new Timer();
updateTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
if (HomeActivity.mHandler != null) { // error
final Message msg = HomeActivity.mHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putString("input", "update");
msg.setData(bundle);
HomeActivity.mHandler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, 0, ONE_SECOND);
}
Broadcast:
public class BluetoothBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i = new Intent(context, BluetoothLeService.class);
context.startService(i);
}
}
}
AndroidManifest:
<!-- Start the service when phone is boot. -->
<receiver android:name="com.example.BluetoothBroadcast" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
probably should be closer to this:
private void createHandler() {
Thread thread = new Thread() {
public void run() {
Looper.prepare();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do Work
handler.removeCallbacks(this);
Looper.myLooper().quit();
}
}, 2000);
Looper.loop();
}
};
thread.start();
}
code for calculating start and end time of scan. Calling scanTime as soon as the scan starts and retTime as soon as the results are received, however, getting two retTimes and the difference between scanTime and retTime is not consistent
public void startService() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (location != null) {
retTime = System.currentTimeMillis() / 1000L;
Log.i("end", Long.toString(retTime));
sendResults(wifi.getScanResults(), androidID, Long.toString(retTime), location);
Long result = retTime - scanTime;
} else {
Log.i("Location", "is Missing");
}
}
};
context.registerReceiver(br, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
t = new Thread(new Runnable() {
public void run() {
try {
setSleepTime(dataTimeDifference);
while (!Thread.interrupted()) {
wifi.startScan();
scanTime = System.currentTimeMillis() / 1000L;
Log.i("start", Long.toString(scanTime));
Thread.sleep(sleepingTime);
}
} catch (InterruptedException e) {
}
}
});
t.start();
}
In short, you know the scan is complete when the BroadcastReceiver is triggered.
This may not directly answer your question, but it seems that this might be a better way of implementing the functionality that you want.
Instead of using Thread.sleep() and a while loop in your Runnable, just rely on the BroadcastReceiver in order to determine when to start a new scan.
Also keep in mind that both the user and the OS can initiate scans, and your BroadcastReceiver will be triggered when those scans complete as well.
private final Runnable mStartScan = new Runnable() {
#Override
public void run() {
wifi.startScan();
}
};
public void startService() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)){
if (location != null) {
sendResults(wifi.getScanResults(), androidID, Long.toString(retTime), location);
} else {
Log.i("Location", "is Missing");
}
t = new Thread(mStartScan);
t.start();
}
}
};
context.registerReceiver(br, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
t = new Thread(mStartScan);
t.start();
}
I want to check some web API and do something per x minutes. I think I should write a service on Android (is there any other solution?).
But how can do that?
I am thinking about writing a service class and in the manifest file I should add this line:
<service
android:name="com.xx.yy.noti_check"
android:enabled="true"
>
</service>
And in my noti_check class I check my web API like this on onStartCommand:
public class noti_check extends Service {
Context mcont;
private Handler myhandler ;
private long RETRY_TIME = 15000;
private long START_TIME = 2000;
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onStart(Intent intent, int startId) {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mcont=this;
myhandler= new Handler();
myhandler.postDelayed(myRunnable, START_TIME);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
try {
myhandler.removeCallbacks(myRunnable);
}
catch (Exception e) {
// TODO: handle exception
}
}
private Runnable myRunnable = new Runnable() {
public void run() {
try {
new get_notifyalert(mcont).execute("") ;
}
catch (Exception e) {
// TODO: handle exception
}
myhandler.postDelayed(myRunnable, RETRY_TIME);
}
};
}
Is this is the right way?
Is this the right way?
No. Only have a service running when it is actively delivering value to the user. Watching the clock tick is not actively delivering value to the user. Use AlarmManager for periodic work like this.