My location service not sends location after disconnection - android

I have a simple application that collects locations. it works without for some minutes or hours but if I disconnect or loose Internet connection, or for disable/enable GPS 4-5 or more times, it not sends connection updates anymore. and I have to restart phone most times or kill that app and start it again (some times not works again after restart) to get locations again.
My application have a simple activity and a service for running in foreground and collection and sending them to server.
Here is my code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.shetapp.ranandeg">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="mydefaultnotificationchannel" />
<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">
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyLocationTrackerService"
android:enabled="true"
android:exported="true" />
<service android:name=".MyFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
This is my activity :
public class MainActivity extends AppCompatActivity {
private final String TAG = "myapp-ma";
public static final String _TAG = "myapp-ma";
public static Context context;
private WebView webViewBrowser;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: main activity created.");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
loadPrefs(getApplicationContext());
getControles();
setBrowser();
startService(new Intent(this , MyLocationTrackerService.class));
}
#Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: main activity destroyed.");
super.onDestroy();
}
#Override
protected void onResume() {
Log.d(TAG, "onResume: main activity resumed.");
super.onResume();
loadPrefs(getApplicationContext());
startService(new Intent(this , MyLocationTrackerService.class));
}
public void loadPrefs(Context context) {
Log.d(TAG, "loadPrefs: fired!");
SharedPreferences pref = getApplicationContext().getSharedPreferences(AppConfig.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
MyLocationTrackerService.USER_TOKEN = pref.getString(AppConfig.SHARED_PREFERENCES_USER_TOKEN , "xxx");
}
protected void getControles() {
Log.d(TAG, "getControles: fired!");
webViewBrowser = (WebView) findViewById(R.id.activity_main_webViewBrowser);
WebAppInterface.wv = webViewBrowser;
}
protected void setBrowser() {
webViewBrowser.addJavascriptInterface(new WebAppInterface(this), "NativeInterface");
WebSettings webSettings = webViewBrowser.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webViewBrowser.setWebViewClient(new MyWebViewClient());
webViewBrowser.setWebChromeClient(new MyWebChromeClient());
webViewBrowser.loadUrl("file:///android_asset/www/index.html");
}
#Override
public void onBackPressed() {
if(webViewBrowser.canGoBack() == true) {
webViewBrowser.goBack();
} else {
MainActivity.super.onBackPressed();
}
}
}
Location tracker service :
public class MyLocationTrackerService extends Service
{
private static final String TAG = "myapp-mlts";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1 * 60 * 1000; // MINUTES*60*1000
private static final float LOCATION_DISTANCE = 0f; // 100f;
public static String USER_TOKEN = "";
private static final int NOTIF_ID = 1;
private static final String NOTIF_CHANNEL_ID = "Channel_Id";
private BroadcastReceiver mRegistrationBroadcastReceiver;
private class LocationListener implements android.location.LocationListener
{
Location mLastLocation;
public LocationListener(String provider)
{
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location)
{
Log.d(TAG, "onLocationChanged: location change detected , "+location.getProvider());
mLastLocation.set(location);
updateServerLocation(getApplication() , location , AppConfig.SERVER_IP , MyLocationTrackerService.USER_TOKEN);
}
#Override
public void onProviderDisabled(String provider)
{
Log.d(TAG, "LocationListener onProviderDisabled , "+provider);
}
#Override
public void onProviderEnabled(String provider)
{
Log.d(TAG, "LocationListener onProviderEnabled , "+provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.d(TAG, "LocationListener onStatusChanged , " + provider);
}
protected void updateServerLocation(Context context, final Location location , final String ip , final String userToken)
{
Log.d(TAG, "LocationListener updateServerLocation, token/server : "+userToken+"/"+ip);
if(ip.equals("")){
Log.d(TAG , "ip of server is empty string. returned.");
} else if(!isConnected()){
Log.d(TAG, "updateServerLocation: not connected!");
} else if(userToken.length() < 1){
Log.d(TAG, "updateServerLocation: userToken.length() < 1 , userToken is : "+userToken);
} else {
String url = ip + "/app/ranande/location";
StringRequest request = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
Log.d(TAG, "onResponse: " + response);
} catch (Exception e){
Log.d(TAG, "onResponse: " + e.getMessage().toString());
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse: " + error.toString());
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
String token = userToken;
if( token.equals(null) || token.equals("") ){
Log.d(TAG , "token is empty string, returned.");
}
params.put("token", token);
params.put("latitude", String.valueOf(location.getLatitude()));
params.put("longitude", String.valueOf(location.getLongitude()));
return params;
}
};
VolleyController.getInstance(context).addToRequestQueue(request);
}
}
}
LocationListener[] mLocationListeners = new LocationListener[] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER)
};
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "MyLocationTrackerService onStartCommand fired.");
startForeground();
try{
Log.d(TAG, "MyLocationTrackerService onStartCommand: token/ip are "+MyLocationTrackerService.USER_TOKEN+"/"+AppConfig.SERVER_IP);
} catch (Exception ex){
Log.d(TAG, "onStartCommand: Exception! : "+ex.toString());
}
try{
super.onStartCommand(intent, flags, startId);
} catch (Exception ex){
Log.e(TAG, "onStartCommand: Exception on calling super.onStartCommand," +ex.toString());
}
return START_STICKY;
}
#Override
public void onCreate()
{
Log.d(TAG, "MyLocationTrackerService created.");
initializeLocationManager();
try {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//use checkSelfPermission()
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} else {
//simply use the required feature
//as the user has already granted permission to them during installation
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
}
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "network provider does not exist, " + ex.getMessage());
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (java.lang.SecurityException ex) {
Log.d(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
#Override
public void onDestroy()
{
Log.d(TAG, "MyLocationTrackerService destroyed.");
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.d(TAG, "fail to remove location listners, ignore", ex);
}
}
}
}
private void initializeLocationManager() {
try{
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
} catch (Exception ex) {
Log.d(TAG, "initializeLocationManager: error : "+ex.toString());
}
}
public Boolean isConnected(){
ConnectivityManager connectivityManager = (ConnectivityManager)getApplicationContext().getSystemService(MainActivity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isConnected()){
return true;
}
return false;
}
private void startForeground() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
startForeground(NOTIF_ID, new NotificationCompat.Builder(this,
NOTIF_CHANNEL_ID) // don't forget create a notification channel first
.setOngoing(true)
.setContentTitle(getString(R.string.app_name))
.setContentText("running ...")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.globe)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round))
.build());
}
}
After restart phone, my application works without any issue, some times I have to kill the Application from application manager and run it again but some times I have to restart the phone.
I think maybe there is an bug with phones GPS or android OS not mine App.
IS THERE ANY ERROR IN MY CODE? or how I could change and solve this problem? Is it good idea to use fuse/google service instead?

Related

Location not updated on 10 mins of interval

I want to track the user location. So I have made a code so that on every 10 mins of interval its location should be hit on server. If it is not moving also the location should hit at 10 min of interval. I set Location interval minutes for 10 min public static final long LOCATION_INTERVAL_MINUTES = 10 * 60 * 1000;
It should update the location with 10 min, but it hits randomly. I also increase the gps frequency distance from 10 to gpsFreqInDistance = 100 .Random hits are stopped but it will not updated on 10 mins of interval.
So what to do to get location at 10 min of interval.
Below is my manifiest
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
As for Android above 10version u cant use background location and foreground location simultaneously. So i comment the ACCESS_BACKGROUND_LOCATION" in my project.
public class LocationMonitoringService implements LocationListener, GpsStatus.Listener {
private static final String TAG = LocationMonitoringService.class.getSimpleName();
private Context mContext;
private LocationRepository mLocationRepository;
private ShareLocationAdapterClass mAdapter;
private SyncOfflineRepository syncOfflineRepository;
private long updatedTime = 0;
private List<UserLocationPojo> mUserLocationPojoList;
private SyncOfflineAttendanceRepository syncOfflineAttendanceRepository;
public LocationMonitoringService(final Context context) {
mContext = context;
mLocationRepository = new LocationRepository(AUtils.mainApplicationConstant.getApplicationContext());
syncOfflineRepository = new SyncOfflineRepository(AUtils.mainApplicationConstant.getApplicationContext());
syncOfflineAttendanceRepository = new SyncOfflineAttendanceRepository(AUtils.mainApplicationConstant.getApplicationContext());
mUserLocationPojoList = new ArrayList<>();
mAdapter = new ShareLocationAdapterClass();
mAdapter.setShareLocationListener(new ShareLocationAdapterClass.ShareLocationListener() {
#Override
public void onSuccessCallBack(boolean isAttendanceOff) {
if (isAttendanceOff && !syncOfflineAttendanceRepository.checkIsAttendanceIn()) {
AUtils.setIsOnduty(false);
((MyApplication) AUtils.mainApplicationConstant).stopLocationTracking();
}
}
#Override
public void onFailureCallBack() {
}
});
}
public void onStartTacking() {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//Exception thrown when GPS or Network provider were not available on the user's device.
try {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
criteria.setAltitudeRequired(false);
criteria.setSpeedRequired(true);
criteria.setCostAllowed(false);
criteria.setBearingRequired(false);
//API level 9 and up
criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);
int gpsFreqInDistance = 100;
assert locationManager != null;
locationManager.addGpsStatusListener(this);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
Log.d(TAG, "onStartTacking: " + e.getLocalizedMessage());
e.printStackTrace();
} catch (RuntimeException e) {
Log.e(TAG, Objects.requireNonNull(e.getLocalizedMessage()));
Log.d(TAG, "onStartTacking: " + e.getMessage());
e.printStackTrace();
}
}
public void onStopTracking() {
mAdapter.shareLocation();
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(this);
}
/*
* LOCATION CALLBACKS
*/
//to get the location change
#Override
public void onLocationChanged(Location location) {
Log.d("okh ", "onLocationChanged: "+System.currentTimeMillis());
if (location != null) {
Log.d(TAG, String.valueOf(location.getAccuracy()));
if (!AUtils.isNullString(String.valueOf(location.getLatitude())) && !AUtils.isNullString(String.valueOf(location.getLongitude()))) {
Prefs.putString(AUtils.LAT, String.valueOf(location.getLatitude()));
Prefs.putString(AUtils.LONG, String.valueOf(location.getLongitude()));
if (Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY, false)) {
if (updatedTime == 0) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
if ((updatedTime + AUtils.LOCATION_INTERVAL_MINUTES) <= System.currentTimeMillis()) {
updatedTime = System.currentTimeMillis();
Log.d(TAG, "updated Time ==== " + updatedTime);
}
sendLocation();
}
}
} else {
Log.d(TAG, "onLocationChanged: no location found !!");
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged" + provider + "Status" + status);
}
#Override
public void onProviderEnabled(String provider) {
Log.d(TAG, " onProviderEnabled" + provider);
}
#Override
public void onProviderDisabled(String provider) {
Log.d(TAG, " onProviderDisabled" + provider);
}
#Override
public void onGpsStatusChanged(int event) {
}
private void sendLocation() {
// mAdapter.shareLocation(getTempList());
Log.d("okh", "sendLocation: Current Time In Millies "+ System.currentTimeMillis());
try {
Calendar CurrentTime = AUtils.getCurrentTime();
Calendar DutyOffTime = AUtils.getDutyEndTime();
if (CurrentTime.before(DutyOffTime)) {
Log.i(TAG, "Before");
UserLocationPojo userLocationPojo = new UserLocationPojo();
userLocationPojo.setUserId(Prefs.getString(AUtils.PREFS.USER_ID, ""));
userLocationPojo.setLat(Prefs.getString(AUtils.LAT, ""));
userLocationPojo.setLong(Prefs.getString(AUtils.LONG, ""));
double startLat = Double.parseDouble(Prefs.getString(AUtils.LAT, "0"));
double startLng = Double.parseDouble(Prefs.getString(AUtils.LONG, "0"));
userLocationPojo.setDistance(String.valueOf(AUtils.calculateDistance(
AUtils.mainApplicationConstant.getApplicationContext(), startLat, startLng)));
// userLocationPojo.setDatetime(AUtils.getServerDateTime()); //TODO
userLocationPojo.setDatetime(AUtils.getServerDateTimeLocal());
userLocationPojo.setOfflineId("0");
if (AUtils.isInternetAvailable() && AUtils.isConnectedFast(mContext))
userLocationPojo.setIsOffline(true);
else
userLocationPojo.setIsOffline(false);
String UserTypeId = Prefs.getString(AUtils.PREFS.USER_TYPE_ID, AUtils.USER_TYPE.USER_TYPE_GHANTA_GADI);
if (AUtils.isInternetAvailable()) {
TableDataCountPojo.LocationCollectionCount count = syncOfflineRepository.getLocationCollectionCount(AUtils.getLocalDate());
if ((UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_GHANTA_GADI) || UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_WASTE_MANAGER))
&& (count.getLocationCount() > 0 || count.getCollectionCount() > 0)) {
syncOfflineRepository.insetUserLocation(userLocationPojo);
} else {
mUserLocationPojoList.add(userLocationPojo);
mAdapter.shareLocation(mUserLocationPojoList);
mUserLocationPojoList.clear();
}
} else {
if (UserTypeId.equals(AUtils.USER_TYPE.USER_TYPE_EMP_SCANNIFY)) {
Type type = new TypeToken<UserLocationPojo>() {
}.getType();
mLocationRepository.insertUserLocationEntity(new Gson().toJson(userLocationPojo, type));
} else {
syncOfflineRepository.insetUserLocation(userLocationPojo);
}
mUserLocationPojoList.clear();
}
}
else {
Log.i(TAG, "After");
syncOfflineAttendanceRepository.performCollectionInsert(mContext,
syncOfflineAttendanceRepository.checkAttendance(), AUtils.getCurrentDateDutyOffTime());
AUtils.setIsOnduty(false);
((MyApplication) AUtils.mainApplicationConstant).stopLocationTracking();
Activity activity = ((Activity) AUtils.currentContextConstant);
if (activity instanceof DashboardActivity) {
((Activity) AUtils.currentContextConstant).recreate();
AUtils.DutyOffFromService = true;
}
if (!AUtils.isNull(AUtils.currentContextConstant)) {
((Activity) AUtils.currentContextConstant).recreate();
}
}
} catch (Exception e) {
e.printStackTrace();
}
Below is the foreground service which i have used
public class ForgroundService extends Service {
private LocationMonitoringService monitoringService;
private Handler locationHandler;
private Runnable locationThread;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
monitoringService = new LocationMonitoringService(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Toast.makeText(this, " MyService Started", Toast.LENGTH_LONG).show();
Log.d("okh", "onCreate: " +System.currentTimeMillis());
Log.d("okh", "onStartCommand: ");
final int currentId = startId;
locationThread = new Runnable() {
public void run() {
monitoringService.onStartTacking();
}
};
locationHandler = new Handler(Looper.getMainLooper());
locationHandler.post(locationThread);
startLocationForeground();
return Service.START_STICKY;
// return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
//Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
locationHandler.removeCallbacks(locationThread);
monitoringService.onStopTracking();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
stopForeground(STOP_FOREGROUND_REMOVE);
}
if(Prefs.getBoolean(AUtils.PREFS.IS_ON_DUTY,false))
{
Intent broadcastIntent = new Intent(this, RestarterBroadcastReceiver.class);
sendBroadcast(broadcastIntent);
}
}
private void startLocationForeground() {
if (Build.VERSION.SDK_INT >= 26) {
String channelId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? this.createNotificationChannel("my_service", "My Background Service")
: "";
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder((Context) this,
channelId);
Notification notification = notificationBuilder
.setOngoing(true)
.setContentText("Please don't kill the app from background. Thank you!!")
.setSmallIcon(getNotificationIcon(notificationBuilder))
.setPriority(-2)
.setCategory("service")
.build();
startForeground(101, notification);
}
}
#RequiresApi(26)
private String createNotificationChannel(String channelId, String channelName) {
NotificationChannel chan = new NotificationChannel(channelId, (CharSequence)channelName,
NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager service = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
service.createNotificationChannel(chan);
return channelId;
}
private int getNotificationIcon(NotificationCompat.Builder notificationBuilder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int color = 0x008000;
notificationBuilder.setColor(color);
return R.drawable.ic_noti_icon;
}
return R.drawable.ic_noti_icon;
}
}
Why you are passing null in the last parameter? Did you try without passing that?
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, AUtils.LOCATION_INTERVAL,
gpsFreqInDistance, this, null);
First of all Google Location Services are far better than Traditional LocationManager to achieve this requirement.
https://developer.android.com/training/location/request-updates

Get current location with background service Android

I'm trying to get the user's locations in real time using service. The problem happens when I try to do this below Android 8.0 because of the foreground service, I looked for several ways to do this but I didn't find any that work below Android 8.0.
Code that i used:
MainActivity
public class MainActivity extends AppCompatActivity {
#BindView(R.id.btn_start_tracking)
Button btnStartTracking;
#BindView(R.id.btn_stop_tracking)
Button btnStopTracking;
#BindView(R.id.txt_status)
TextView txtStatus;
public BackgroundService gpsService;
public boolean mTracking = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
final Intent intent = new Intent(this.getApplication(), BackgroundService.class);
this.getApplication().startService(intent);
this.getApplication().startForegroundService(intent);
this.getApplication().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
#OnClick(R.id.btn_start_tracking)
public void startLocationButtonClick() {
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
gpsService.startTracking();
mTracking = true;
toggleButtons();
}
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
if (response.isPermanentlyDenied()) {
openSettings();
}
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
}
}).check();
}
#OnClick(R.id.btn_stop_tracking)
public void stopLocationButtonClick() {
mTracking = false;
gpsService.stopTracking();
toggleButtons();
}
private void toggleButtons() {
btnStartTracking.setEnabled(!mTracking);
btnStopTracking.setEnabled(mTracking);
txtStatus.setText( (mTracking) ? "TRACKING" : "GPS Ready" );
}
private void openSettings() {
Intent intent = new Intent();
intent.setAction( Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
String name = className.getClassName();
if (name.endsWith("BackgroundService")) {
gpsService = ((BackgroundService.LocationServiceBinder) service).getService();
btnStartTracking.setEnabled(true);
txtStatus.setText("GPS Ready");
}
}
public void onServiceDisconnected(ComponentName className) {
if (className.getClassName().equals("BackgroundService")) {
gpsService = null;
}
}
};
}
Background service class
public class BackgroundService extends Service {
private final LocationServiceBinder binder = new LocationServiceBinder();
private final String TAG = "BackgroundService";
private LocationListener mLocationListener;
private LocationManager mLocationManager;
private NotificationManager notificationManager;
private final int LOCATION_INTERVAL = 500;
private final int LOCATION_DISTANCE = 10;
#Override
public IBinder onBind(Intent intent) {
return binder;
}
private class LocationListener implements android.location.LocationListener {
private Location lastLocation = null;
private final String TAG = "LocationListener";
private Location mLastLocation;
public LocationListener(String provider) {
mLastLocation = new Location(provider);
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
Log.i(TAG, "LocationChanged: "+location);
}
#Override
public void onProviderDisabled(String provider) {
Log.e(TAG, "onProviderDisabled: " + provider);
}
#Override
public void onProviderEnabled(String provider) {
Log.e(TAG, "onProviderEnabled: " + provider);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.e(TAG, "onStatusChanged: " + status);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onCreate() {
Log.i(TAG, "onCreate");
startForeground(12345678, getNotification());
}
#Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListener);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
}
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
public void startTracking() {
initializeLocationManager();
mLocationListener = new LocationListener(LocationManager.GPS_PROVIDER);
try {
mLocationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, mLocationListener);
} catch (java.lang.SecurityException ex) {
// Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
// Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
public void stopTracking() {
this.onDestroy();
}
private Notification getNotification() {
NotificationChannel channel = new NotificationChannel("channel_01", "My Channel", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(getApplicationContext(), "channel_01").setAutoCancel(true);
return builder.build();
}
public class LocationServiceBinder extends Binder {
public BackgroundService getService() {
return BackgroundService.this;
}
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ac.myapp">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<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">
<activity android:name=".maps"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:enabled="true"
android:name=".BootUpReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name=".BackgroundService"/>
</application>
</manifest>

Audio thread SIP Android

I have a connection with SIP server(Asterisk), but micro and dynamics doesn't work. Asterisk kicks client in 31 seconds(Empty RTP thread). Documentation by Google says:
Android provides an API that supports the Session Initiation Protocol (SIP). This lets you add SIP-based internet telephony features to your applications. Android includes a full SIP protocol stack and integrated call management services that let applications easily set up outgoing and incoming voice calls, without having to manage sessions, transport-level communication, or audio record or playback directly.
Activity + Receiver:
public class MainActivity extends AppCompatActivity {
public String domain = "192.168.10.37";
public String name = "111";
public String password = "123456";
public String sipAddress = "100#192.168.10.37";
public IncomingCallReceiver receiver;
public SipManager sipManager;
public SipProfile sipProfile;
public SipAudioCall call;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.USE_SIP)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.USE_SIP)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.USE_SIP},
0);
}
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("zlotnikov.SIPexample.INCOMING_CALL");
receiver = new IncomingCallReceiver();
this.registerReceiver(receiver, intentFilter);
initManager();
}
private void initManager() {
if (sipManager == null) {
sipManager = SipManager.newInstance(this);
}
}
private void initializeLocalProfile() {
if (sipProfile != null) {
closeLocalProfile();
}
try {
SipProfile.Builder builder = new SipProfile.Builder(name, domain);
builder.setPassword(password);
builder.setSendKeepAlive(true);
builder.setAutoRegistration(true);
sipProfile = builder.build();
Intent intent = new Intent();
intent.setAction("zlotnikov.SIPexample.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
SipRegistrationListener listener = new SipRegistrationListener() {
#Override
public void onRegistering(String s) {
System.out.println("voip onRegistering " + s);
}
#Override
public void onRegistrationDone(String s, long l) {
System.out.println("voip onRegistrationDone " + s + " " + l);
//initCall();
}
#Override
public void onRegistrationFailed(String s, int i, String s1) {
System.out.println("voip onRegistrationFailed " + s);
}
};
sipManager.open(sipProfile, pendingIntent, null);
//sipManager.register(sipProfile, 40, listener);
sipManager.setRegistrationListener(sipProfile.getUriString(), listener);
} catch (ParseException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
}
}
#Override
protected void onStart() {
super.onStart();
initializeLocalProfile();
}
#Override
protected void onStop() {
super.onStop();
closeLocalProfile();
}
private void closeLocalProfile() {
try {
if (sipProfile != null) {
sipManager.close(sipProfile.getUriString());
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
private void initCall() {
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
super.onCallEstablished(call);
System.out.println("voip onCallEstablished");
call.startAudio();
call.setSpeakerMode(true);
}
#Override
public void onCallEnded(SipAudioCall call) {
super.onCallEnded(call);
System.out.println("voip onCallEnded");
}
};
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
} catch (SipException e) {
closeLocalProfile();
call.close();
e.printStackTrace();
System.out.println("voip MainActivity Конец соединения");
}
}
public class IncomingCallReceiver extends BroadcastReceiver {
private MediaPlayer mediaPlayer;
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
System.out.println("voip Пришел звонок " + intent.toString());
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
System.out.println("voip onRinging()");
try {
startRinging();
} catch (Exception e) {
stopRinging();
System.out.println("voip onRinging exception");
e.printStackTrace();
}
}
#Override
public void onCallEstablished(SipAudioCall call) {
super.onCallEstablished(call);
System.out.println("voip onCallEstablished()");
stopRinging();
}
#Override
public void onCallEnded(SipAudioCall call) {
super.onCallEnded(call);
System.out.println("voip onCallEnded()");
}
};
incomingCall = sipManager.takeAudioCall(intent, listener);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
/*if (incomingCall.isMuted()) {
incomingCall.toggleMute();
}*/
//call = incomingCall;
incomingCall.answerCall(30);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
System.out.println("voip IncomingCallReceiver конец соединения");
}
}
}
private synchronized void startRinging() {
long[] pattern = {0, 1000, 1000};
((Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE)).vibrate(pattern, 0);
Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(getApplicationContext(), RingtoneManager.TYPE_RINGTONE);
mediaPlayer = MediaPlayer.create(getApplicationContext(), defaultRingtoneUri);
mediaPlayer.setLooping(true);
mediaPlayer.start();
}
private synchronized void stopRinging() {
((Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE))
.cancel();
if (mediaPlayer != null || mediaPlayer.isPlaying()) mediaPlayer.stop();
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="zlotnikov.sipexample">
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.sip.voip" />
<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">
<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>
<receiver android:name=".MainActivity$IncomingCallReceiver" android:label="Call Receiver" />
</application>

Android Geo-fence not working properly

I am using geofence api for proximity but it is not working properly. some times it gives in range and out range at the same location.
i am also using GPS library to improve accuracy of geofence inrange-outrange but still it is not working properly. i am using below code for geofence :
I am using 300 meters radius for considering inrange-outrange (enter-exit)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.geofencedemo">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CheckPermission"
android:screenOrientation="portrait"
android:theme="#style/DialogActivity" />
<receiver
android:name="services.GeofenceTransitionsReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.geofencedemo.ACTION_RECEIVE_GEOFENCE" />
<category android:name="com.geofencedemo" />
</intent-filter>
</receiver>
<service
android:name="services.GeofenceTransitionsIntentService"
android:exported="false" />
</application>
MainActivity.java (for registering geofence)
public class MainActivity extends Activity implements com.google.android.gms.location.LocationListener {
private LocationManager locationManager;
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private final float GEOFENCE_RADIUS_IN_METERS = 300;//Meter(s)
private final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = Geofence.NEVER_EXPIRE;
private int GEOFENCE_TRANSITION_ENTER = 1;
private int GEOFENCE_TRANSITION_EXIT = 2;
private List<Geofence> mGeofenceList;
private String geofenceID = "testGeofence";
private SharedPreferences preferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preferences = getSharedPreferences("ISSKEYGEOFENCE-prefs", MODE_PRIVATE);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Button btnSetLocation = (Button) findViewById(R.id.btn_setlocation);
btnSetLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGPSEnabled) {
Toast.makeText(getApplicationContext(), "Please enable Location service to allow set location", Toast.LENGTH_LONG).show();
return;
}
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1){
Log.d("myTag", "check marshmallow permission...");
Intent permissionIntent = new Intent(MainActivity.this, CheckPermission.class);
startActivityForResult(permissionIntent, 1111);
} else {
intGoogleAPI();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1111:
if (resultCode == RESULT_OK) {
intGoogleAPI();
}
break;
}
}
private void intGoogleAPI() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(3000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setFastestInterval(1000);
mGeofenceList = new ArrayList<Geofence>(1);
mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this).addApi(LocationServices.API).addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(final Bundle bundle) {
if (isServiceConnected()) {
Log.d("myTag", "request for update current location");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, MainActivity.this);
}
}
#Override
public void onConnectionSuspended(final int cause) {}
}).addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(final ConnectionResult connectionResult) {}
}).build();
mGoogleApiClient.connect();
}
private boolean isServiceConnected() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(MainActivity.this);
return ConnectionResult.SUCCESS == resultCode;
}
#Override
public void onLocationChanged(Location mLastLocation) {
if (isServiceConnected()) {
Log.d("myTag", "request removed location update");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
try {
addLocation(mLastLocation.getLatitude(), mLastLocation.getLongitude());
} catch (Exception e) {}
}
public void addLocation(final double latitude, final double longitude) {
Log.v("myTag", "set lcation lat: " + latitude);
Log.v("myTag", "set lcation lag: " + longitude);
mGeofenceList.add(new Geofence.Builder().setRequestId(geofenceID).setTransitionTypes(GEOFENCE_TRANSITION_ENTER | GEOFENCE_TRANSITION_EXIT).setCircularRegion(latitude, longitude, GEOFENCE_RADIUS_IN_METERS).setExpirationDuration(GEOFENCE_EXPIRATION_IN_MILLISECONDS).build());
final List<String> GEO_FENCE_ID_LIST = new ArrayList<String>();
GEO_FENCE_ID_LIST.add(geofenceID);
if (mGoogleApiClient != null) {
LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, GEO_FENCE_ID_LIST).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(final Status status) {
if (status.isSuccess()) {
// successfully removed geofence...
Log.d("myTag", "removed old geofence successfully ");
} else {
Log.d("myTag", "Not removed old geofence");
}
}
});
}
if (mGoogleApiClient != null) {
LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, getGeofencingRequest(), getGeofencePendingIntent()).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(final Status status) {
if (status.isSuccess()) {
// successfully Added geofence...
Log.d("myTag", "New geofence successfully added");
Toast.makeText(getApplicationContext(), "Successfully added geofence", Toast.LENGTH_LONG).show();
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("isinrange", false);
editor.putString("lat", String.valueOf(latitude));
editor.putString("log", String.valueOf(longitude));
editor.apply();
}
try {
if (isServiceConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, MainActivity.this);
}
mGoogleApiClient.disconnect();
} catch (Exception e) {}
}
});
}
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_EXIT);
builder.addGeofences(mGeofenceList);
return builder.build();
}
private PendingIntent getGeofencePendingIntent() {
Intent intent = new Intent("com.geofencedemo.ACTION_RECEIVE_GEOFENCE");
return PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
GeofenceTransitionsIntentService (Trigger inrange,outrange by geofence)
public class GeofenceTransitionsIntentService extends IntentService implements com.google.android.gms.location.LocationListener {
public GeofenceTransitionsIntentService() {
super("GeofenceTransitionsIntentService");
}
#Override
public void onCreate() {
super.onCreate();
preferences = getSharedPreferences("ISSKEYGEOFENCE-prefs", MODE_PRIVATE);
}
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private boolean isLocationFetched = false;
private String geofenceTransitionIds;
private boolean isInRange = false;
private SharedPreferences preferences;
#Override
protected void onHandleIntent(final Intent intent) {
if (intent.getExtras() != null) {
int geofenceTransitionType = intent.getIntExtra("TransitionType", 4);
geofenceTransitionIds = intent.getStringExtra("TransitionId");
/*final String lat = intent.getStringExtra("TransitionId_lat");
final String log = intent.getStringExtra("TransitionId_log");*/
if (geofenceTransitionIds != null && geofenceTransitionIds.length() > 0) {
switch (geofenceTransitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
geofenceTransitionIds(geofenceTransitionIds, true);
//new IntGoogleApiClient(appStorage, null, true).Intialize();
//processIn(geofenceTransitionIds, lat, log);
break;
case Geofence.GEOFENCE_TRANSITION_EXIT:
geofenceTransitionIds(geofenceTransitionIds, false);
//new IntGoogleApiClient(appStorage, null, true).Intialize();
//processOut(geofenceTransitionIds, lat, log);
break;
}
}
}
}
private void geofenceTransitionIds (String geofenceTransitionIds, boolean isEnteCall) {
if (geofenceTransitionIds != null && geofenceTransitionIds.length() > 0) {
isInRange = isEnteCall;
intGoogleAPI();
}
}
private void intGoogleAPI() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(3000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setFastestInterval(1000);
mGoogleApiClient = new GoogleApiClient.Builder(GeofenceTransitionsIntentService.this).addApi(LocationServices.API).addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(final Bundle bundle) {
if (isServiceConnected()) {
// please consider here location permission is already allowed...
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, GeofenceTransitionsIntentService.this);
}
}
#Override
public void onConnectionSuspended(final int cause) {}
}).addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(final ConnectionResult connectionResult) {}
}).build();
mGoogleApiClient.connect();
}
private boolean isServiceConnected() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(GeofenceTransitionsIntentService.this);
return ConnectionResult.SUCCESS == resultCode;
}
#Override
public void onLocationChanged(Location passedLocation) {
if (passedLocation != null && !isLocationFetched) {
if (isServiceConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, GeofenceTransitionsIntentService.this);
}
isLocationFetched = true;
try {
if (geofenceTransitionIds != null && geofenceTransitionIds.length() > 0) {
if (isInRange) {
processIn(geofenceTransitionIds, String.valueOf(passedLocation.getLatitude()), String.valueOf(passedLocation.getLongitude()));
} else {
processOut(geofenceTransitionIds, String.valueOf(passedLocation.getLatitude()), String.valueOf(passedLocation.getLongitude()));
}
}
} catch (Exception e) {}
disconnectGoogleClient();
}
}
private void disconnectGoogleClient() {
try {
if (mGoogleApiClient != null) {
if (isServiceConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, GeofenceTransitionsIntentService.this);
}
mGoogleApiClient.disconnect();
}
} catch (Exception e) {}
}
private void processIn(String passedIds, String lat, String log) {
if (passedIds != null) {
List<String> items = Arrays.asList(passedIds.split("\\s*,\\s*"));
for (String deviceName : items) {
if (deviceName != null) {
boolean isOutRange = preferences.getBoolean("isinrange", false);
if (mappingRadius(true, deviceName, lat, log) && isOutRange) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("isinrange", false);
editor.apply();
sendNotification(GeofenceTransitionsIntentService.this, "In range come!", Color.BLACK);
}
}
}
}
}
private void processOut(String passedIds, String lat, String log) {
if (passedIds != null) {
List<String> items = Arrays.asList(passedIds.split("\\s*,\\s*"));
for (String deviceName : items) {
if (deviceName != null) {
boolean isInRange = preferences.getBoolean("isinrange", false);
if (mappingRadius(false, deviceName, lat, log) && !isInRange) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("isinrange", true);
editor.apply();
sendNotification(GeofenceTransitionsIntentService.this, "Out range come!", Color.RED);
}
}
}
}
}
private boolean mappingRadius(boolean isInRange, String deviceName, String currentLat, String currentLog) {
final float cLat = Float.parseFloat(currentLat);
final float cLog = Float.parseFloat(currentLog);
Log.d("myTag", "GeofenceTransitionsReceiver lat " + cLat);
Log.d("myTag", "GeofenceTransitionsReceiver log " + cLog);
float appLat;
float appLog;
appLat = Float.parseFloat(preferences.getString("lat", "0.0"));
appLog = Float.parseFloat(preferences.getString("log", "0.0"));
Log.d("myTag", "GeofenceTransitionsReceiver app lat " + appLat);
Log.d("myTag", "GeofenceTransitionsReceiver app log " + appLog);
Location current_latlog = new Location("crntlocation");
current_latlog.setLatitude(appLat);
current_latlog.setLongitude(appLog);
Location new_latlog = new Location("newlocation");
new_latlog.setLatitude(cLat);
new_latlog.setLongitude(cLog);
final double distance = current_latlog.distanceTo(new_latlog);
Log.v("myTag", "GeofenceTransitionsReceiver calculation distance is: " + distance);
//if (distance < 2000) {
if (isInRange) {
if (distance <= 300) { // with in 300 Meters consider as in range...
return true;
} else {
return false;
}
} else {
if (distance >= 300) { // more than 300 Meters consider as out range...
return true;
} else {
return false;
}
}
/*} else {
return false;
}*/
}
private void sendNotification(final Context context, String notificationMessage, int color) {
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(new Intent());
PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher)).setContentTitle(context.getResources().getString(R.string.app_name)).setTicker(notificationMessage).setContentText(notificationMessage).setContentIntent(notificationPendingIntent).setColor(color).setVibrate(new long[] { 1000, 1000, 1000, 1000 }).setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify((int) System.currentTimeMillis(), builder.build());
}
}
GeofenceTransitionsReceiver (handling/calculate distance after geofence trigger)
public class GeofenceTransitionsReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = getErrorString(context, geofencingEvent.getErrorCode());
Log.d("myTag", "GeofenceTransitionsReceiver error " +errorMessage);
// sendNotification(context, errorMessage, Color.RED);
return;
}
int geofenceTransition = geofencingEvent.getGeofenceTransition();
Log.d("myTag", "GeofenceTransitionsReceiver " + geofenceTransition);
// for testing....
//sendNotification(context, context.getResources().getString(R.string.geofence_transition_type, geofenceTransition), Color.RED);
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
String geofenceTransitionIds = getGeofenceTransitionIds(triggeringGeofences);
Location triggeringLocation = geofencingEvent.getTriggeringLocation();
Intent serviceIntent = new Intent(context.getApplicationContext(), GeofenceTransitionsIntentService.class);
serviceIntent.putExtra("TransitionType", geofenceTransition);
serviceIntent.putExtra("TransitionId", geofenceTransitionIds);
serviceIntent.putExtra("TransitionId_lat", String.valueOf(triggeringLocation.getLatitude()));
serviceIntent.putExtra("TransitionId_log", String.valueOf(triggeringLocation.getLongitude()));
context.startService(serviceIntent);
} else {
// sendNotification(context,
// context.getResources().getString(R.string.geofence_transition_invalid_type,
// geofenceTransition), Color.RED);
}
}
private String getErrorString(final Context context, int errorCode) {
Resources mResources = context.getResources();
switch (errorCode) {
case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
return "Geofence service is not available now";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
return "Your app has registered too many geofences";
case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "You have provided too many PendingIntents to the addGeofences() call";
default:
return "Unknown error: the Geofence service is not available now";
}
}
private String getGeofenceTransitionIds(List<Geofence> triggeringGeofences) {
List<String> triggeringGeofencesIdsList = new ArrayList<String>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
return TextUtils.join(",", triggeringGeofencesIdsList);
}
}
Is there anything else we can do to improve accuracy and overcome the problem of inrange outrange at the same location ?

How to call service methods from broadcastReceiver?

I have GPS Tracking application main goal is saving GPS coordinate to backed database every 5 minutes interval. So i created Service & receiver because even my my application doesn't open / run this should work.
After user enter executive code , it create database and go to welcome screen.
In there it start GPS capturing & save it to PDA database calling service to upload. I have receiver, when phone isBooted it start this receiver & receiver call service.
My problem is receiver doesn't call service. It didn't go to Service class.
protected void onStop(){
super.onStop();
if(gpsReceiver != null){
unregisterReceiver(gpsReceiver);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
gpsReceiver = new GpsReceiver();
IntentFilter intentFilter1 = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
intentFilter1.addAction(Intent.ACTION_BOOT_COMPLETED);
intentFilter1.addAction(Intent.ACTION_POWER_CONNECTED);
intentFilter1.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(gpsReceiver, intentFilter1);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MINIMUM_TIME_BETWEEN_UPDATES,
MINIMUM_DISTANCE_CHANGE_FOR_UPDATES,
new MyLocationListener()
);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, new MyLocationListener());
}
private class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
String message = String.format( "Location \n Longitude: %1$s \n Latitude: %2$s", location.getLongitude(), location.getLatitude());
longitude = location.getLongitude();
latitude =location.getLatitude();
//save GPS coordinate to PDA DB
GPSDBAdapter dbAdapter = GPSDBAdapter.getDBAdapterInstance(HomeActivity.this);
dbAdapter.openDataBase();
dbAdapter.insertGPS(longitude, latitude, "MASS", deserializeObject());
dbAdapter.close();
//After save GPS coordinate it upload to backend using service
startService(new Intent(HomeActivity.this, UploadService.class));
Toast.makeText(HomeActivity.this, message, Toast.LENGTH_LONG).show();
}
public void onStatusChanged(String s, int i, Bundle b) {
Toast.makeText(HomeActivity.this, "Provider status changed",Toast.LENGTH_LONG).show();
}
public void onProviderDisabled(String s) {
Toast.makeText(HomeActivity.this,"Provider disabled by the user. GPS turned off",Toast.LENGTH_LONG).show();
}
public void onProviderEnabled(String s) {
Toast.makeText(HomeActivity.this, "Provider enabled by the user. GPS turned on",Toast.LENGTH_LONG).show();
}
}
This is my receiver .
public class GpsReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
int delay = 5000; // delay for 5 sec.
//int period = 1000 *60*5; // repeat every 5min.
int period = 30000; // repeat every 5min.
//TO-REMOVE -TESTING PURPOSE
Intent serviceIntent = new Intent(context,UploadService.class);
context.startService(serviceIntent);
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println(" Receiver done");
Intent serviceIntent = new Intent(context,UploadService.class);
context.startService(serviceIntent);
}
}, delay, period);
}
}
}
This is my service.
public class UploadService extends Service{
private Thread serviceThread = null;
public static final String APPURL = "http://124.43.25.10:8080/Ornox/GPSPulseReceiver";
public static double longitude;
public static double latitude ;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Log.d("========", "onCreate");
Toast.makeText(UploadService.this, "Upload GPS Service Created", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(UploadService.this, "Upload Service Stopped", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(UploadService.this, "Upload Service Started", Toast.LENGTH_LONG).show();
ConnectivityManager manager = (ConnectivityManager) getSystemService(MassGPSTrackingActivity.CONNECTIVITY_SERVICE);
boolean is3g = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting();
boolean isWifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
if(is3g ||isWifi){
if(!APPURL.equals("")){
serviceThread = new ServiceThread();
serviceThread.start();
}
}else {
Toast.makeText(this, "GPRS/WIFI is not available", Toast.LENGTH_LONG).show();
}
}
public void uploadGPSData() {
GPSDBAdapter gpsAdapter = GPSDBAdapter.getDBAdapterInstance(this);
gpsAdapter.openDataBase();
try{
String query = " SELECT ExecutiveCode,CaptureDate,CaptureTime,Longitude,Latitude" +//4
" FROM WMLiveGPSData " +
" WHERE UploadFlag ='1' ";
ArrayList<?> stringList = gpsAdapter.selectRecordsFromDBList(query, null);
System.out.println("==WMLiveGPSData==stringList=="+stringList.size());
gpsAdapter.close();
if(stringList.size() > 0){
for (int i = 0; i < stringList.size(); i++) {
ArrayList<?> arrayList = (ArrayList<?>) stringList.get(i);
ArrayList<?> list = arrayList;
HttpResponse response = null;
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("repc", (String)list.get(0)));
nameValuePairs.add(new BasicNameValuePair("rouc", "SE0160"));
nameValuePairs.add(new BasicNameValuePair("Date", (String)list.get(1)));
nameValuePairs.add(new BasicNameValuePair("Time", (String)list.get(2)));
nameValuePairs.add(new BasicNameValuePair("long", (String)list.get(3)));
nameValuePairs.add(new BasicNameValuePair("lat", (String)list.get(4)));
try {
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 3000000;
HttpConnectionParams.setConnectionTimeout(httpParameters,timeoutConnection);
int timeoutSocket = 5000000; // in milliseconds which is the timeout
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient httpclient = new DefaultHttpClient(httpParameters);
HttpPost method = new HttpPost(APPURL);
// method.setHeader("Content-Type","text/xml");
method.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(method);
System.out.println("==response==" + response);
if (response != null) {
Log.i("login",""+ response.getEntity().getContentLength());
} else {
Log.i("login", "got a null response");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"Could not connect to server. Please Try again",
Toast.LENGTH_SHORT).show();
Log.e("log_tag", "Error in http connection " + e.toString());
}
}
}
}catch (Exception e) {
e.printStackTrace();
}
//return response;
}
private class ServiceThread extends Thread {
#Override
public void run() {
uploadGPSData();
}
};
}
This is my manifest file
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".MassGPSTrackingActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".HomeActivity" android:screenOrientation="unspecified"></activity>
<service android:enabled="true" android:name=".service.UploadService" />
<receiver android:name="com.mass.gps.service.GpsReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.BATTERY_CHANGED" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.SCREEN_ON"/>
<action android:name="android.intent.action." />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_GPS"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Issue is it didn't go to Service class.
Please help me out this question...
Thanks in advance..
i think u r package name is not correct manifest file
<service android:enabled="true" android:name="com.mass.gps.service.UploadService" />
specify your service name as packagename
Use this in the receiver:
Intent i = new Intent();
i.setClassName("com.intelligent.locator", "com.intelligent.locator.AlarmActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);

Categories

Resources