I am developing real time application so i need to send continuous or some periodic (in seconds) location data as latitude and longitude to web service using rest API. so what can i use to send continuous or periodic data to server? do i need to use back ground service or anything else? i don't know how background service work and how to use it? so can anyone help me for this? thanks in advance.
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
displayLocation();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
Toast.makeText(getApplicationContext(), "Location changed!",
Toast.LENGTH_SHORT).show();
displayLocation();
}
you need to make a service for that if you want to send data continuous to the server even after your application is closed.
Here is how i made my service.
public class FeatureService extends Service
{
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
// make your api call here and other implementations according to your requirement.
super.onCreate();
}
#Override
public void onDestroy()
{
// what you want when service is destroyed
}
Declare your service in Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="Your Serive"
android:enabled="true">
</service>
</application>
And Finally call your service like this in onCreate of your relevant activity.
Intent i= new Intent(this,FeatureService.class);
startService(i);
Get the lat and Long Values, then Schedule a periodic task to run the method to send value to the server
you can use Job Scheduler (https://developer.android.com/reference/android/app/job/JobScheduler.html)
or
You can use android-job/evernote to do a periodic Task
(https://github.com/evernote/android-job)
private void schedulePeriodicJob() {
int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
.setPeriodic(TimeUnit.MINUTES.toMillis(15), TimeUnit.MINUTES.toMillis(5))
.setPersisted(true)
.build()
.schedule();
}
Related
I am developing an application that sends location data to a database. As I need this task to be executed in the background, I used the Service type to send the data, but when the application goes to the background, the service stops executing after a few seconds. I researched the subject and found the JobScheduler class, but this class performs services in the background with a very long time interval (15min) and I needed the service to be performed at least every 2 min and to be canceled only by the user. Is there a way to do this? I thank anyone who can help.
https://developer.android.com/reference/android/app/job/JobScheduler
My service:
public class GPSservice extends Service {
private String TAG = "INICIAR SERVIÇO GPS";
private Context context;
private HandlerThread handlerThread;
private Handler handler;
private final int TEMPO_ENTRE_NOTIFICAÇOES_SEGUNDOS = 60; //tempo de sessenta segundos
#Override
public void onCreate() {
handlerThread = new HandlerThread("HandlerThread");
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
//Previne que seja executado em subsequentes chamadas a onStartCommand
if(!handlerThread.isAlive()) {
Log.d("NotifyService","Notificações iniciadas");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
AtualizarLocalizacaoBanco();
handler.postDelayed(this, 1000 * TEMPO_ENTRE_NOTIFICAÇOES_SEGUNDOS);
}
};
handler.post(runnable);
}
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("NotifyService","Notificações Finalizadas");
Intent broadcastIntent = new Intent(this, BroadCastReceiver.class);
sendBroadcast(broadcastIntent);
//handlerThread.quit();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
}
public void AtualizarLocalizacaoBanco(){
context = this;
ModeloAtualizacao model = new ModeloAtualizacao();
SharedPreferences preferences = this.context.getSharedPreferences("user_preferences", MODE_PRIVATE);
model.setId(preferences.getString("usuario_id", ""));
model.setLati(preferences.getString("user_latitude", ""));
model.setLongi(preferences.getString("user_longitude", ""));
model.setEmpresa(preferences.getString("usuario_empresa", ""));
model.setEscola(preferences.getString("usuario_escola", ""));
Call<String> call = new RetrofitConfig().postAtualizacao().atualizarLocalizacao(model);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d("Sucesso: ", "ok");
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.d("Erro atualizar", t.getMessage());
}
});
}
Manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true">
<activity android:name=".ActivityGPS"></activity>
<activity android:name=".Activity_Lista_Aluno" />
<activity
android:name=".ProfessorActivity"
android:label="#string/title_activity_professor" />
<service
android:name=".GPSservice"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>
<activity
android:name=".MainActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity android:name=".Activity_Login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
I need to be able to receive incoming Twilio calls regardless of whether the app is currently running or not.
Once the user has started the app and logged into our server, I start the service shown below.
The Service is started sticky, and at no point is stopService or stopSelf etc ever called, so the service should still be running after the App is closed.
When the App is running, IncomingCallActivity starts fine in response to a Twilio call.
If the App is in the background, IncomingCallActivity still starts fine in response to a Twilio call.
If however the App is closed, IncomingCallActivity no longer starts in response to a Twilio call.
Why isn't IncomingCallActivity started if the App has been closed??
public class CallService extends Service implements Twilio.InitListener, DeviceListener, ConnectionListener {
private Device mDevice;
private Connection mConnection;
#Override
public void onCreate() {
super.onCreate();
registerBroadcastReceiver();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Initialize the Twilio SDK if required
if (!Twilio.isInitialized()) {
Twilio.initialize(getApplicationContext(), this);
} else {
getCapabilityToken("CallService", getUser());
}
...
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
// Unregister broadcast receiver
final LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
super.onDestroy();
}
#Override
public void onInitialized() {
getCapabilityToken("CallService", getUser());
}
#Override
public void onError(Exception e) {
}
private void getCapabilityToken(String string, User user) {
// Request the capability token from the server.
...
}
protected void setCapabilityToken() {
// Create device using the capability token
mDevice = Twilio.createDevice(getUser().capabilityToken, this);
// Set pending intent for Twilio device
Intent intent = new Intent(this, IncomingCallActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mDevice.setIncomingIntent(pendingIntent);
// Broadcast that CallService is ready, to any registered receivers
Intent broadcastIntent = new Intent(App.ACTION__TWILIO_SERVICE_READY);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
public void connect() {
mConnection = mDevice.connect(null /* parameters */, null /* ConnectionListener */);
if (mConnection == null) {
...
} else {
...
}
}
private void answerCall(Device device, Connection connection) {
if (mConnection != null) {
mConnection.disconnect();
}
mConnection = connection;
mConnection.accept();
}
/**
* BroadcastReceiver
*/
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
switch (action) {
case App.ACTION__CAPABILITY_TOKEN_OBTAINED:
setCapabilityToken();
break;
case App.ACTION__CONNECT:
connect();
break;
}
}
};
#Override
public void onStartListening(Device device) {
}
#Override
public void onStopListening(Device device) {
}
#Override
public void onStopListening(Device device, int i, String s) {
}
#Override
public boolean receivePresenceEvents(Device device) {
return false;
}
#Override
public void onPresenceChanged(Device device, PresenceEvent presenceEvent) {
}
#Override
public void onConnecting(Connection connection) {
}
#Override
public void onConnected(Connection connection) {
}
#Override
public void onDisconnected(Connection connection) {
}
#Override
public void onDisconnected(Connection connection, int i, String s) {
}
}
Edit:
To clarify how I've declared my services etc, here is my AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest package="au.com.encall.encall"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".IncomingCallActivity"
android:screenOrientation="portrait"/>
<service android:name=".services.CallService"/>
<service android:name=".services.DownloadService"/>
<service
android:name="com.twilio.client.TwilioClientService"
android:exported="false"
android:stopWithTask="false" />
<meta-data
... />
...
</application>
</manifest>
if you are using twilio demo than You need to service in Androidmenifest
<service android:name="com.twilio.client.TwilioClientService" android:exported="false" android:stopWithTask="true"/>
its working for me.
twilio provide their own service. so you need to just declare it on menifest.so does't need to create new service.
jusr remove this service and put it on android menifest.it will automatically start after app close.
Its Work for me no need extra service
<service android:name="com.twilio.client.TwilioClientService" android:exported="false" android:stopWithTask="false"/>
But How can we Handle if token is Expired ? At that time IncomingCallActivity no longer starts
I'm trying to use Data Items to send a few strings through to my wear, but my wear never seems to receive any signal, because onDataChanged() is never called. I even set a time stamp to ensure the data is always different whenever it is sent.
Is there a specific way I have to install the app onto both devices to get it to work? I'm just clicking run and selecting my phone, then switching modules and doing the same for my wear device.
Here is the code from my main activity on my phone:
public class HomeActivity extends Activity{
public static String TAG = "HomeActivity";
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.home_view);
Button mButton = (Button) findViewById(R.id.send_button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendData();
}
});
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
}).addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}).addApi(Wearable.API)
.build();
mGoogleApiClient.connect();
}
private void sendData(){
if (mGoogleApiClient!=null){
return;
}
final PutDataMapRequest putRequest = PutDataMapRequest.create("/SAMPLE");
final DataMap map = putRequest.getDataMap();
map.putInt("color", Color.RED);
map.putLong("date", new Date().getTime());
Wearable.DataApi.putDataItem(mGoogleApiClient, putRequest.asPutDataRequest());
}
}
And here is the code on my wearable:
public class LayoutFaceService extends CanvasWatchFaceService implements DataApi.DataListener{
#Override
public void onCreate(){
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected");
Wearable.DataApi.addListener(mGoogleApiClient, LayoutFaceService.this);
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
})
.build();
mGoogleApiClient.connect();
}
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_DELETED) {
Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
} else if (event.getType() == DataEvent.TYPE_CHANGED) {
Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
}
}
}
And my wear manifest :
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault" >
<service
android:name=".LayoutFaceService"
android:label="#string/my_digital_name"
android:permission="android.permission.BIND_WALLPAPER" >
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/watch_face" />
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="#drawable/preview_digital" />
<meta-data
android:name="com.google.android.wearable.watchface.preview_circular"
android:resource="#drawable/preview_digital_circular" />
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
In sendData(), your conditional seems to be incorrect; mGoogleApiClient != null is true so you exit right there. Address that and see whether you can get any further; there might be other issues but that is the first obvious one. If that didn't completely fix your issue, then make sure you also include the manifest on your phone in your post.
I'm having some problems with services.
Service:
public class MyService extends Service {
public MyService() {
}
private static final String TAG = "AutoService";
private Timer timer;
private TimerTask task;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Auto Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
int delay = 5000; // delay for 5 sec.
int period = 5000; // repeat every sec.
timer = new Timer();
timer.scheduleAtFixedRate(task = new TimerTask(){
public void run()
{
System.out.println("done");
}
}, delay, period);
}
#Override
public boolean stopService(Intent name) {
timer.cancel();
task.cancel();
return super.stopService(name);
}
#Override
public void onDestroy(){
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
MainActivity:
public class ClientSocket extends ActionBarActivity {
CheckBox enablecheck;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client_socket);
enablecheck = (CheckBox)findViewById(R.id.enablecheck);
enablecheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(enablecheck.isChecked()){
startService(new Intent(ClientSocket.this, MyService.class));
}else
{
stopService(new Intent(ClientSocket.this, MyService.class));
}
}
});
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.Light" >
<activity
android:name=".ClientSocket"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
I'm just testing, when I try to stop the service, the fuction onDestroy() is called but don't stop the service. The service/android:exported and android:enable both are true.
Any help?
The Timer instance create a background thread. If you want to stop the service completely you also need to stop the thread. Timer has a cancel() method you can call in the onDestroy() method to terminate the Timer.
Also, exporting the service means other applications (processes) can access it. You most likely don't need that.
The issue in the code is a misunderstanding of what
#Override
public boolean stopService(Intent name) {
timer.cancel();
task.cancel();
return super.stopService(name);
}
really does.
It is not a callback that is called when the service is stopped. Instead it is overriding the stopService method on Context, which you call to stop a service (as you do in the Activity in your example).
In fact the override of stopServicein your code has no effect at all.
timer.cancel();
task.cancel();
should be placed in the onDestroy method of your service.
I'm new in android programming.So please help me..
I'm developing an app in which it continuously monitors the current location.I want he app to run in background even if the user goes for an other app.He will be able to stop the location updates whenhe returns to my app.Everything is working fine until i do an outgoing call.I'm not able to remove location updates after the outgoing call..
Below is my code..
tb_trackstartstop.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked)
{
trackflag=true;
tracklistener(HomeActivity.this);
}
else
{
if(trackflag)
trackmlocManager.removeUpdates(trackmlocListener);
trackflag=false;
Toast.makeText(HomeActivity.this, "Stopped", Toast.LENGTH_LONG).show();
}
}
and my code for onpause and onresume is as follows
#Override
protected void onPause()
{
super.onPause();
bundle.putBoolean("trackflagState", trackflag);
}
#Override
protected void onResume()
{
super.onResume();
trackflag=bundle.getBoolean("trackflagState",false);
}
Use BroadcastReceiver
Register receiver in Manifest:
<receiver android:name=".MyCallReciever">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
Permission in manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Receiver class:
public class MyCallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
//Unregister the location listener here.
}
}
}
Hope this helps.