I'm using the following code to change two text views based on when the user turns on/off their network and their GPS. I was able to get the network text view to work but not the location text view. I think I am using the wrong filter, but I don't know which to use instead. Any suggestions/answers?
public class MainActivity extends AppCompatActivity {
TextView networkTextView;
TextView locationTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
networkTextView = findViewById(R.id.networkTextView);
locationTextView = findViewById(R.id.locationTextView);
IntentFilter filter1 = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(broadcastReceiver1, filter1);
IntentFilter filter2 = new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION);
registerReceiver(broadcastReceiver2, filter2);
}
BroadcastReceiver broadcastReceiver1 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
boolean noNetworkConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noNetworkConnectivity) {
networkTextView.setText("Disconnected");
} else {
networkTextView.setText("Connected");
}
}
}
};
BroadcastReceiver broadcastReceiver2 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(intent.getAction())) {
boolean noLocationConnectivity = intent.getBooleanExtra(LocationManager.PROVIDERS_CHANGED_ACTION, false);
if (noLocationConnectivity) {
locationTextView.setText("Disconnected");
} else {
locationTextView.setText("Connected");
}
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver1);
unregisterReceiver(broadcastReceiver2);
}
}
Update:
In the broadcast receiver for the location I replaced
boolean noLocationConnectivity = intent.getBooleanExtra(LocationManager.PROVIDERS_CHANGED_ACTION, false);
with
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean locationConnectivity = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
but that didn't work. Maybe need to request location data permission from user?
Update 2:
Realized that it is registering boolean changes of the LocationManager.GPS_provider, but not initially. Only after the Location setting is manually changed after the app is started does the text change, unlike with the network check that changes the text as soon as the app starts.
I think that this question has already been answered here
But I'm thinking if use LocationManager and LocationListener is a good idea or not, I mean, LocationListener has those overrided methods:
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
I leave it to your consideration
Related
I have created a service that has a LocationListener.
In the Fragment i have a BroadcastReceiver that successfully receives location from the Service. Everything works fine when the phone is connected to my computer and I have pressed "run" (not debug mode). I receive location continuously when the screen on my phone is turned off as I can see in the "Run" console in Android Studio.
However when i disconnect my phone from the computer and turn the screen off, I stoped receiving location updates. Or I got only one or two location updates before it stoped. Then when turning the screen on again the Service starts sending location updates.
I have tried using a WakeLock on the Fragment and the Service, but it dosent seem to have any effect.
Can someone help me please!?... :,(
In my Service I set a ArrayList->String in putExtra() that contains a Latitude and a TimeStamp so that I can see if the locationlistener did update location when screen is locked. And in the Fragment I display the results in the view so that I can manually debug.
Here is my Service code:
public class GpsService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private Intent mIntent;
private ArrayList<String> latTimeArrayList = new ArrayList<>();
private PowerManager.WakeLock wakeLock;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
mIntent = new Intent("location_update");
PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
return START_NOT_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
mIntent.putExtra("Latitude", location.getLatitude());
mIntent.putExtra("Longitude", location.getLongitude());
if(latTimeArrayList.size() < 10){
latTimeArrayList.add(location.getLatitude() + " -> " + new Date());
}else if(latTimeArrayList.size() == 10){
mIntent.putExtra("latTimeArray", latTimeArrayList);
}
sendBroadcast(mIntent);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
//noinspection MissingPermission
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100, 0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0, listener);
}
#Override
public void onDestroy() {
super.onDestroy();
if(locationManager != null){
//noinspection MissingPermission
locationManager.removeUpdates(listener);
wakeLock.release();
}
}
}
private BroadcastReceiver broadcastReceiver;
ArrayList<String> aString = new ArrayList<>();
private String mmtext = "";
TextView debugtext = (TextView) mView.findViewById(R.id.hasCompletedTrack);
int doagain = 0;
#Override
public void onResume() {
super.onResume();
if(broadcastReceiver == null){
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try{
if (doagain == 0){
aString = (ArrayList<String>)intent.getExtras().get("latTimeArray");
if(aString != null || aString.size() != 0){
for (int i =0; i< aString.size(); i++){
mmtext += aString.get(i) + "\n";
}
doagain = 1;
debugtext.setText(mmtext);
}
}
}catch(NullPointerException e){}
I found the answer...
I had to turn off PoweSaving mode on my Samsung Galaxy S6 edge.
Also, in my broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
that's in my Fragment, I did some position calculations for every location update that I got from my Service with a Intent getExtra() (this is not in the code I posted). However onReceive() only gets triggered when the screen is on(not locked). Therefore my calculations in the fragment were never triggered, only when the screen was on it triggered the calculation methods.
My solution to this was to handle all the calculations directly in my service.
The thing is that I'm trying on the emulator, and it works but only once I press the "send location to device" on the emulator but before that I don't have the chance to get the location....How do I get the location for the first time using this service?. I don't have a real device right know and the emulator is my only way of testing this for now.....I tried to send a 0,0 at first to see if that would trigger a location update but it's not working as well......any ideas?
#SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private String lastKnownLatitude;
private String lastKnownLongitude;
private Boolean isFirstTime=true;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
broadcastLocation("0","0");
listener= new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
lastKnownLatitude=""+location.getLatitude();
lastKnownLongitude=""+location.getLongitude();
Log.d("LOCATION-UPDATE",lastKnownLatitude+" long:"+lastKnownLongitude);
broadcastLocation(lastKnownLatitude,lastKnownLongitude);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
Log.d("GPS-Stat-Changed",s);
}
#Override
public void onProviderEnabled(String s) {
Log.d("GPS-Provider-Enabled",s);
}
#Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,0,listener);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
Log.d("LAST_LAT_AND_LONG",lastKnownLatitude+" "+lastKnownLongitude);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "I'm still getting user coordinates", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
public void broadcastLocation(String latitude,String longitude){
Intent intentSendLocationMainActivity = new Intent("location_update");
intentSendLocationMainActivity.putExtra("latitude",latitude);
intentSendLocationMainActivity.putExtra("longitude",longitude);
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
}
EDIT: This is the complete service working. For the first time it gets the coordinates with the getLastKnownLocation() and the on sucesive times with the listener onLocationChanged()
#SuppressWarnings("MissingPermission")
public class GPSService extends Service {
private LocationListener listener;
private LocationManager locationManager;
private String lastKnownLatitude;
private String lastKnownLongitude;
private Boolean isFirstTime=true;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
listener= new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//To transfer the data to the main activity I use broadcast receiver in the main activity, using an intent filter location_update
Intent intentSendLocationMainActivity = new Intent("location_update");
lastKnownLatitude=""+location.getLatitude();
lastKnownLongitude=""+location.getLongitude();
Log.d("LOCATION-UPDATE",lastKnownLatitude+" long:"+lastKnownLongitude);
broadcastLocation(lastKnownLatitude,lastKnownLongitude);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
Log.d("GPS-Stat-Changed",s);
}
#Override
public void onProviderEnabled(String s) {
Log.d("GPS-Provider-Enabled",s);
}
#Override
public void onProviderDisabled(String s) {
Intent activateGPSIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activateGPSIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activateGPSIntent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission, listen for updates every 3 seconds
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,0,listener);
Map<String, String> coordinates=getLastKnownLocation(locationManager);
broadcastLocation(coordinates.get("latitude"),coordinates.get("longitude"));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ClearFromRecentService", "Service Started");
Log.d("LAST_LAT_AND_LONG",lastKnownLatitude+" "+lastKnownLongitude);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ClearFromRecentService", "Service Destroyed, Removing update location listener");
//unregistering the listener
/*if(locationManager != null){
locationManager.removeUpdates(listener);
}*/
}
public void onTaskRemoved(Intent rootIntent) {
Log.e("ClearFromRecentService", "END");
//here you can call a background network request to post you location to server when app is killed
Toast.makeText(getApplicationContext(), "I'm still getting user coordinates", Toast.LENGTH_LONG).show();
//stopSelf(); //call this method to stop the service
}
private void broadcastLocation(String latitude,String longitude){
Intent intentSendLocationMainActivity = new Intent("location_update");
intentSendLocationMainActivity.putExtra("latitude",latitude);
intentSendLocationMainActivity.putExtra("longitude",longitude);
//I need to differentiate here if the app is killed or not to send the location to main activity or to a server
sendBroadcast(intentSendLocationMainActivity);
}
private Map<String, String> getLastKnownLocation(LocationManager lm){
Location lastKnownLocation=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
String ll=""+lastKnownLocation.getLatitude();
Map<String, String> coordinates = new HashMap<String, String>();
// Check everytime this value, it may be null
if(lastKnownLocation != null){
coordinates.put("latitude",""+lastKnownLocation.getLatitude());
coordinates.put("longitude",""+lastKnownLocation.getLongitude());
}else{
coordinates.put("latitude","0");
coordinates.put("longitude","0");
}
return coordinates;
}
}
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
Location lastKnownLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
// Check everytime this value, it may be null
if(lastKnownLocation != null){
double latitude = lastKnownLocation.getLatitude();
double longitude = lastKnownLocation.getLongitude();
// Use values as you wish
}
broadcastLocation("0","0");
....
}
I'm trying to implement service in android to make an app locker.
I'm trying to check the which activity is running on the foreground and if it's locked, forwarding it to my Locker activity.
I've added the service in manifest too, but it isn't working at all.
Here's the code `
private static Timer timer = new Timer();
public Boolean userAuth = false;
private Context mContext;
public String pActivity = "";
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate() {
super.onCreate();
mContext = this;
startService();
}
private void startService() {
timer.scheduleAtFixedRate(new mainTask(), 0, 500);
}
private class mainTask extends TimerTask {
public void run() {
toastHandler.sendEmptyMessage(0);
}
}
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Stopped ...", Toast.LENGTH_SHORT).show();
}
private final Handler toastHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String activityOnTop;
ActivityManager manager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> tasks = manager.getRunningAppProcesses();
//Getting the foreground activity name
activityOnTop=tasks.get(0).processName;
//Checking it against the app I need to lock
if (activityOnTop.equalsIgnoreCase("com.droiddigger.techmanik")) {
Intent lockIntent = new Intent(mContext, Lockscreen.class);
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(lockIntent);
} else if(activityOnTop.equalsIgnoreCase("com.droiddigger.applocker")){
}else{
}
}
};
You must start that service. It can be done in an Activity or a BroadcastReceiver.
startService(new Intent(this, UpdaterServiceManager.class));
For example:
public class MyActivity extends Activity {
#Override
public void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this, YourService.class));
finish();
}
}
EDIT:
You are always retrieving the item 0 of the list called tasks. Looking at the SDK documentation, it is said that list order is not especified: https://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses()
Returns a list of RunningAppProcessInfo records, or null if there are
no running processes (it will not return an empty list). This list
ordering is not specified.
You must get the current visible activity other way. I suggest an AccessibilityService
I'm trying to write a service to locate the user by it's GPs location in Android. I wrotre a service for that. But alwasy when I try to start the service the error
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want? appears. I already searched for this problem on google and added the follwoing line to my sourcecode:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
But the Error still appears. What can I do in order to make the service start without any errors? Here is my code:
MainActivity.java:
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
//GPs Standort bestimmung starten
Intent intent;
intent = new Intent(this, Gps_Service.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
initButtons();
}
}
"Gps_service.java":
public class Gps_Service extends Service implements LocationListener{
private double längengrad = 0.0, breitengrad = 0.0;
LocationManager locationManager;
Address adresse;
String straße, Ort, Land;
#Override
public void onCreate(){
super.onCreate();
locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(locationManager.GPS_PROVIDER, 10000, 100, this);
}
#Override
public void onDestroy(){
super.onDestroy();
locationManager.removeUpdates(this);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onLocationChanged(Location location) {
längengrad = location.getLongitude();
breitengrad = location.getLatitude();
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
Instead of running a service to retreive the user's location via GPS, use Google's Fused Location API.
The link provided has a detailed guide about how to implement it and is much more reliable and accurate in receiving location data.
Don't forget this gradle dependency as well:
compile 'com.google.android.gms:play-services-location:8.4.0'
I'm implementing running the service in background and service will be stop and start click on toggle button.Service is start in 1st activity and stop the service in another activity when click on toggle button.When i run the application service is automatically start in 1st activity which i start in onCreate() method in 1st activity and another activity toggle button status is already on status but when i toggle button is going to off service stop but when i back to 1st activity service is again start.Please can any one help me.Here is my code
public class MyService extends Service
{
private static final String TAG = "MyService";
MediaPlayer player;
private final String StrMyService="myservice";
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.braincandy);
player.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
}
}
public class Service_Demo extends Activity implements OnClickListener
{
private static final String TAG = "ServicesDemo";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
System.out.println("In OnCreate(");
startService(new Intent(this, MyService.class));
}
}
public class Toggle_Activity extends Activity
{
ToggleButton tgButton;
private boolean isService=false;
private String strService;
public final String service_Prefs="servicePrefs";
private static final String StrMyService = "zdf";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.toggle);
final SharedPreferences servicePrefs=this.getSharedPreferences("Service_Prefs",MODE_WORLD_READABLE);
strService=servicePrefs.getString(StrMyService , "myservice");
Log.e("",""+strService);
final boolean mBool = servicePrefs.getBoolean("myservice", true);
Log.e("Boolean Value mBool","="+mBool);
Boolean b = mBool;
Log.e("Update pref", b.toString());
tgButton = (ToggleButton)findViewById(R.id.toggleButton);
tgButton.setChecked(mBool);
final boolean mBool1 = servicePrefs.getBoolean("myservice", false);
final Boolean c = mBool1;
Log.e("Update pref", c.toString());
tgButton=(ToggleButton)findViewById(R.id.toggleButton);
tgButton.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if(tgButton.isChecked())
{
startService(new Intent(Toggle_Activity.this , MyService.class));
System.out.println("Service is started in togglr button");
}
else
{
stopService(new Intent(Toggle_Activity.this,MyService.class));
System.out.println("Service is stopped in togglr button");
}
}
});
}
}
in the first activity, you'd put startService(new Intent(this, MyService.class)) in onresume
from oncreate
I figured this out the best way possible. I basically linked my toggle button and my service together using a shared preference and listeners. I called this shared preference "service_running" and then implemented my listeners in the activity onCreate() method the toggle button is present in (in this case, MainActivity.
In my onCreate() heres what I did:
// set toggle button based on service running
final ToggleButton toggle = (ToggleButton)findViewById(R.id.toggleButton);
toggle.setChecked(serviceRunning(SendService.class));
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged (CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
startSendService();
}
else {
stopSendService();
}
}
});
// set shared pref listener for toggle
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.OnSharedPreferenceChangeListener myPrefListner = new SharedPreferences.OnSharedPreferenceChangeListener(){
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("service_running")) {
toggle.setChecked(prefs.getBoolean("service_running", false));
}
}
};
prefs.registerOnSharedPreferenceChangeListener(myPrefListner);
startSendService() and stopSendService() simply start or stop my service depending on if it is running and has the correct app permissions or not.
Heres the method which checks if a service is running (credit to #geekQ in this thread):
private boolean serviceRunning (Class<?> serviceClass) {
// check if a service class is currently running
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
And then in my service, in the onStartCommand() I just changed the shared preference to true, and in the onDestroy() I changed it to false.
The only caveat with this is that you have to hide this shared preference from your preference screen, which can be done with:
getPreferenceScreen().removePreference(findPreference("service_running"));