The question is published on by Tutorial Guruji team.
Updated 13-10-2014: added togglegps.class
Hello i have a simple proyect with two buttons to start and stop a gps service.
as soon as i click the start button to start the service the aplication shuts down.
i get the following logcat
10-12 14:23:18.424: I/Choreographer(1300): Skipped 36 frames! The application may be doing too much work on its main thread. 10-12 14:23:18.504: D/gralloc_goldfish(1300): Emulator without GPU emulation detected. 10-12 14:24:07.794: E/Google(1300): Service Created 10-12 14:24:07.834: D/AndroidRuntime(1300): Shutting down VM 10-12 14:24:07.864: W/dalvikvm(1300): threadid=1: thread exiting with uncaught exception (group=0xb2a3fba8) 10-12 14:24:07.894: E/AndroidRuntime(1300): FATAL EXCEPTION: main 10-12 14:24:07.894: E/AndroidRuntime(1300): Process: com.example.newtrack, PID: 1300 10-12 14:24:07.894: E/AndroidRuntime(1300): java.lang.RuntimeException: Unable to start service com.example.newtrack.AndroidLocationServices@b2d1b4e8 with Intent { cmp=com.example.newtrack/.AndroidLocationServices }: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE from pid=1300, uid=10052 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2719) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityThread.access$2100(ActivityThread.java:135) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.os.Handler.dispatchMessage(Handler.java:102) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.os.Looper.loop(Looper.java:136) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityThread.main(ActivityThread.java:5017) 10-12 14:24:07.894: E/AndroidRuntime(1300): at java.lang.reflect.Method.invokeNative(Native Method) 10-12 14:24:07.894: E/AndroidRuntime(1300): at java.lang.reflect.Method.invoke(Method.java:515) 10-12 14:24:07.894: E/AndroidRuntime(1300): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) 10-12 14:24:07.894: E/AndroidRuntime(1300): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 10-12 14:24:07.894: E/AndroidRuntime(1300): at dalvik.system.NativeStart.main(Native Method) 10-12 14:24:07.894: E/AndroidRuntime(1300): Caused by: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE from pid=1300, uid=10052 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.os.Parcel.readException(Parcel.java:1465) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.os.Parcel.readException(Parcel.java:1419) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:2373) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1127) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:365) 10-12 14:24:07.894: E/AndroidRuntime(1300): at com.example.newtrack.ToggleGPS.turnGPSOn(ToggleGPS.java:53) 10-12 14:24:07.894: E/AndroidRuntime(1300): at com.example.newtrack.AndroidLocationServices.onStart(AndroidLocationServices.java:58) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.Service.onStartCommand(Service.java:450) 10-12 14:24:07.894: E/AndroidRuntime(1300): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2702) 10-12 14:24:07.894: E/AndroidRuntime(1300): ... 10 more 10-12 14:24:11.544: I/Process(1300): Sending signal. PID: 1300 SIG: 9
what can be the causes that i can not start the service? what can i add to the mainactivity?
the manifest has all the permissions and the services are registered
the following is my mainactivity
package com.example.newtrack; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //start the service public void onClickStartServie(View V) { //start the service from here //MyService is your service class name startService(new Intent(this, AndroidLocationServices.class)); } //Stop the started service public void onClickStopService(View V) { //Stop the running service from here//MyService is your service class name //Service will only stop if it is already running. stopService(new Intent(this, AndroidLocationServices.class)); } }
as stated above it has only two onclicks for start and stop service
the main service that is called is the following
package com.example.newtrack; import org.json.JSONArray; import org.json.JSONObject; import android.app.Service; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.util.Log; public class AndroidLocationServices extends Service { WakeLock wakeLock; private LocationManager locationManager; public AndroidLocationServices() { // TODO Auto-generated constructor stub } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); PowerManager pm = (PowerManager) getSystemService(this.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DoNotSleep"); // Toast.makeText(getApplicationContext(), "Service Created", // Toast.LENGTH_SHORT).show(); Log.e("Google", "Service Created"); } @Override @Deprecated public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); new ToggleGPS(getApplicationContext()).turnGPSOn(); // Toast.makeText(getApplicationContext(), "Service Started", // Toast.LENGTH_SHORT).show(); Log.e("Google", "Service Started"); locationManager = (LocationManager) getApplicationContext() .getSystemService(Context.LOCATION_SERVICE); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5, listener); } private LocationListener listener = new LocationListener() { @Override public void onLocationChanged(Location location) { // TODO Auto-generated method stub Log.e("Google", "Location Changed"); if (location == null) return; if (isConnectingToInternet(getApplicationContext())) { JSONArray jsonArray = new JSONArray(); JSONObject jsonObject = new JSONObject(); try { Log.e("latitude", location.getLatitude() + ""); Log.e("longitude", location.getLongitude() + ""); jsonObject.put("latitude", location.getLatitude()); jsonObject.put("longitude", location.getLongitude()); jsonArray.put(jsonObject); Log.e("request", jsonArray.toString()); new LocationWebService().execute(new String[] { Constants.TRACK_URL, jsonArray.toString() }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } }; @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); new ToggleGPS(getApplicationContext()).turnGPSOff(); wakeLock.release(); } public static boolean isConnectingToInternet(Context _context) { ConnectivityManager connectivity = (ConnectivityManager) _context .getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo[] info = connectivity.getAllNetworkInfo(); if (info != null) for (int i = 0; i < info.length; i++) if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } return false; } }
i also post my manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.newtrack" android:versionCode="1" android:versionName="1.0" > <!-- Permissions to record locations --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.newtrack.MainActivity" 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="com.example.newtrack.AndroidLocationServices" /> <receiver android:name="AlarmReceiver" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> </application> </manifest>
the class i use to turn on gps is the following
import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.provider.Settings; /** * * @author Atish Agrawal * */ public class ToggleGPS { Context context; public ToggleGPS(Context context) { this.context = context; } public boolean canToggleGPS() { PackageManager pacman = context.getPackageManager(); PackageInfo pacInfo = null; try { pacInfo = pacman.getPackageInfo("com.android.settings", PackageManager.GET_RECEIVERS); } catch (NameNotFoundException e) { return false; // package not found } if (pacInfo != null) { for (ActivityInfo actInfo : pacInfo.receivers) { // test if recevier is exported. if so, we can toggle GPS. if (actInfo.name .equals("com.android.settings.widget.SettingsAppWidgetProvider") && actInfo.exported) { return true; } } } return false; // default } public void turnGPSOn() { Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE"); intent.putExtra("enabled", true); this.context.sendBroadcast(intent); String provider = Settings.Secure.getString( context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); if (!provider.contains("gps")) { // if gps is disabled final Intent poke = new Intent(); poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); poke.addCategory(Intent.CATEGORY_ALTERNATIVE); poke.setData(Uri.parse("3")); this.context.sendBroadcast(poke); } } public void turnGPSOff() { String provider = Settings.Secure.getString( context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); if (provider.contains("gps")) { // if gps is enabled final Intent poke = new Intent(); poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); poke.addCategory(Intent.CATEGORY_ALTERNATIVE); poke.setData(Uri.parse("3")); this.context.sendBroadcast(poke); } } }
if possible please indicate what i should change – following comments made by @neo
any comments are apreciated
thank you very much.
Answer
You can see that the exception line below in the trace:
10-12 14:24:07.894: E/AndroidRuntime(1300): at com.example.newtrack.ToggleGPS.turnGPSOn(ToggleGPS.java:53)
This was a bug before that let you enable the settings by sending the broadcast(that is fixed now). So you will need to ask the User to manually enable the GPS settings using the Intent given below.
startActivity(context, new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));