Android设备如何通过程序控制GPS开关

11

我正在使用以下代码来控制GPS的开/关。

//Enable GPS
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
context.sendBroadcast(intent);
//Disable GPS
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
context.sendBroadcast(intent);

我需要在安卓设备上通过程序开关GPS。我使用了上述代码,但它并不能在所有设备上正常工作。


可能是ICS Android enable gps programmatically?的重复问题。 - NickT
5个回答

27

根据我的个人经验,我来回答这个问题:

  • 你在问题中展示的黑客代码已经停止在Android 4.4版本上工作。你将从Kitkat版本开始遇到以下异常:java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE

  • 第一个答案的代码不再起作用,它只在通知栏中显示动画GPS图标。

  • 出于安全目的,Google开发者已经阻止了之前运行良好的两种方法。

  • 因此,结论是你无法通过编程方式启动或关闭GPS。


谢谢您宝贵的回答。那么,有没有其他方法可以打开/关闭GPS? - Shrikant Salunkhe
@ShrikantSalunkhe,欢迎您。现在唯一的方式是手动完成,而不能通过编程来实现。 - Lucifer
1
startActivity(context, new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); 启动活动(context,新意图(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - Faisal Ashraf
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)); 你也可以使用can并导航到用户的设置页面。 - Faisal Ashraf
@Faisal Ashraf - 但它不能自动打开/关闭GPS。 - MikeL

2

试用以下代码:

/** Method to turn on GPS **/
    public void turnGPSOn(){
        try
        {

        String provider = Settings.Secure.getString(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"));
            sendBroadcast(poke);
        }
        }
        catch (Exception e) {

        }
    }
// Method to turn off the GPS
    public void turnGPSOff(){
        String provider = Settings.Secure.getString(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"));
            sendBroadcast(poke);
        }
    }

    // turning off the GPS if its in on state. to avoid the battery drain.
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        turnGPSOff();`enter code here`
    }

    /**

Also add this on your manifest:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>

更新:

现在我们可以使用默认的启用位置对话框(如Google地图)从我们的应用程序中开启/关闭GPS。

文档可以在此处找到:

Android位置对话框

示例代码:

if (googleApiClient == null) {
        googleApiClient = new GoogleApiClient.Builder(getActivity())
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
            googleApiClient.connect();

            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(30 * 1000);
            locationRequest.setFastestInterval(5 * 1000);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

            //**************************
            builder.setAlwaysShow(true); //this is the key ingredient
            //**************************

            PendingResult<LocationSettingsResult> result =
                    LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
            result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
                @Override
                public void onResult(LocationSettingsResult result) {
                    final Status status = result.getStatus();
                    final LocationSettingsStates state = result.getLocationSettingsStates();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            // All location settings are satisfied. The client can initialize location
                            // requests here.
                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            // Location settings are not satisfied. But could be fixed by showing the user
                            // a dialog.
                            try {
                                // Show the dialog by calling startResolutionForResult(),
                                // and check the result in onActivityResult().
                                status.startResolutionForResult(
                                        getActivity(), 1000);
                            } catch (IntentSender.SendIntentException e) {
                                // Ignore the error.
                            }
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            // Location settings are not satisfied. However, we have no way to fix the
                            // settings so we won't show the dialog.
                            break;
                    }
                }
            });           
  }

哦,我还没有在4.4上测试过它。 - kgandroid
在4.4版本中,它会触发安全异常。 - Shrikant Salunkhe
在版本4.4.2中,触发安全异常“Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE”,因此在4.4及以上版本中将不再起作用。 - Yohanim
SettingsApi现已过时。建议使用新的(类似的)代码,链接在这里:https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient - ARLabs

2

这段代码只能在已经获取Root权限的手机上运行。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);



        String[] cmds = {"cd /system/bin" ,"settings put secure location_providers_allowed +gps"};
        try {
            Process p = Runtime.getRuntime().exec("su");
            DataOutputStream os = new DataOutputStream(p.getOutputStream());
            for (String tmpCmd : cmds) {
                os.writeBytes(tmpCmd + "\n");
            }
            os.writeBytes("exit\n");
            os.flush();
        }
        catch (IOException e){
            e.printStackTrace();
        }

    }
}

-1

使用此代码打开GPS,反转条件以关闭GPS

Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
 intent.putExtra("enabled", true);
 this.ctx.sendBroadcast(intent);

String provider = Settings.Secure.getString(ctx.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.ctx.sendBroadcast(poke);


}

之前似乎存在一个破坏安全性的错误,但他们在最新的API中进行了修复。参考链接:https://code.google.com/p/android/issues/detail?id=35924 - Sanket Pandya

-3
我建议您在Android KitKat 4.4.x中使用以下代码。
   public class GPSService extends Service implements LocationListener 


   {
// saving the context for later use
private final Context mContext;
// if GPS is enabled
boolean isGPSEnabled = false;
// if Netw`enter code here`ork is enabled
boolean isNetworkEnabled = false;
// if Location co-ordinates are available using GPS or Network
public boolean isLocationAvailable = false;

// Location and co-ordinates coordinates
Location mLocation;
double mLatitude;
double mLongitude;

// Minimum time fluctuation for next update (in milliseconds)
private static final long TIME = 30000;
// Minimum distance fluctuation for next update (in meters)
private static final long DISTANCE = 20;

// Declaring a Location Manager
protected LocationManager mLocationManager;

public GPSService(Context context) {
    this.mContext = context;
    mLocationManager = (LocationManager) mContext
            .getSystemService(LOCATION_SERVICE);

}

/**
 * Returs the Location
 * 
 * @return Location or null if no location is found
 */
public Location getLocation() {
    try {

        // Getting GPS status
        isGPSEnabled = mLocationManager
                .isProviderEnabled(LocationManager.GPS_PROVIDER);

        // If GPS enabled, get latitude/longitude using GPS Services
        if (isGPSEnabled) {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, TIME, DISTANCE, this);
            if (mLocationManager != null) {
                mLocation = mLocationManager
                        .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (mLocation != null) {
                    mLatitude = mLocation.getLatitude();
                    mLongitude = mLocation.getLongitude();
                    isLocationAvailable = true; // setting a flag that
                                                // location is available
                    return mLocation;
                }
            }
        }

        // If we are reaching this part, it means GPS was not able to fetch
        // any location
        // Getting network status
        isNetworkEnabled = mLocationManager
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (isNetworkEnabled) {
            mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, TIME, DISTANCE, this);
            if (mLocationManager != null) {
                mLocation = mLocationManager
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                if (mLocation != null) {
                    mLatitude = mLocation.getLatitude();
                    mLongitude = mLocation.getLongitude();
                    isLocationAvailable = true; // setting a flag that
                                                // location is available
                    return mLocation;
                }
            }
        }
        // If reaching here means, we were not able to get location neither
        // from GPS not Network,
        if (!isGPSEnabled) {
            // so asking user to open GPS
            askUserToOpenGPS();
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    // if reaching here means, location was not available, so setting the
    // flag as false
    isLocationAvailable = false;
    return null;
}

/**
 * Gives you complete address of the location
 * 
 * @return complete address in String
 */
public String getLocationAddress() {

    if (isLocationAvailable) {

        Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());
        // Get the current location from the input parameter list
        // Create a list to contain the result address
        List<Address> addresses = null;
        try {
            /*
             * Return 1 address.
             */
            addresses = geocoder.getFromLocation(mLatitude, mLongitude, 1);
        } catch (IOException e1) {
            e1.printStackTrace();
            return ("IO Exception trying to get address:" + e1);
        } catch (IllegalArgumentException e2) {
            // Error message to post in the log
            String errorString = "Illegal arguments "
                    + Double.toString(mLatitude) + " , "
                    + Double.toString(mLongitude)
                    + " passed to address service";
            e2.printStackTrace();
            return errorString;
        }
        // If the reverse geocode returned an address
        if (addresses != null && addresses.size() > 0) {
            // Get the first address
            Address address = addresses.get(0);
            /*
             * Format the first line of address (if available), city, and
             * country name.
             */
            String addressText = String.format(
                    "%s, %s, %s",
                    // If there's a street address, add it
                    address.getMaxAddressLineIndex() > 0 ? address
                            .getAddressLine(0) : "",
                    // Locality is usually a city
                    address.getLocality(),
                    // The country of the address
                    address.getCountryName());
            // Return the text
            return addressText;
        } else {
            return "No address found by the service: Note to the developers, If no address is found by google itself, there is nothing you can do about it.";
        }
    } else {
        return "Location Not available";
    }

}



/**
 * get latitude
 * 
 * @return latitude in double
 */
public double getLatitude() {
    if (mLocation != null) {
        mLatitude = mLocation.getLatitude();
    }
    return mLatitude;
}

/**
 * get longitude
 * 
 * @return longitude in double
 */
public double getLongitude() {
    if (mLocation != null) {
        mLongitude = mLocation.getLongitude();
    }
    return mLongitude;
}

/**
 * close GPS to save battery
 */
public void closeGPS() {
    if (mLocationManager != null) {
        mLocationManager.removeUpdates(GPSService.this);
    }
}

/**
 * show settings to open GPS
 */
public void askUserToOpenGPS() {
    AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(mContext);

    // Setting Dialog Title
    mAlertDialog.setTitle("Location not available, Open GPS?")
    .setMessage("Activate GPS to use use location services?")
    .setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            mContext.startActivity(intent);
            }
        })
        .setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
                }
            }).show();
}

/** 
 * Updating the location when location changes
 */
@Override
public void onLocationChanged(Location location) {
    mLatitude = location.getLatitude();
    mLongitude = location.getLongitude();
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}}

/////////////////////////

                                                                                                                     public class MainActivity extends ActionBarActivity {
     @Override
             public class MainActivity extends ActionBarActivity {protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container,
                false);

        final TextView tvLocation = (TextView)rootView.findViewById(R.id.tvLocation);
        final TextView tvAddress = (TextView)rootView.findViewById(R.id.tvAddress);

        Button btnGetLocation = (Button)rootView.findViewById(R.id.btnGetLocation);

        btnGetLocation.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                String address = "";
                GPSService mGPSService = new GPSService(getActivity());
                mGPSService.getLocation();

                if (mGPSService.isLocationAvailable == false) {

                    // Here you can ask the user to try again, using return; for that
                    Toast.makeText(getActivity(), "Your location is not available, please try again.", Toast.LENGTH_SHORT).show();
                    return;

                    // Or you can continue without getting the location, remove the return; above and uncomment the line given below
                    // address = "Location not available";
                } else {

                    // Getting location co-ordinates
                    double latitude = mGPSService.getLatitude();
                    double longitude = mGPSService.getLongitude();
                    Toast.makeText(getActivity(), "Latitude:" + latitude + " | Longitude: " + longitude, Toast.LENGTH_LONG).show();

                    address = mGPSService.getLocationAddress();

                    tvLocation.setText("Latitude: " + latitude + " \nLongitude: " + longitude);
                    tvAddress.setText("Address: " + address);
                }

                Toast.makeText(getActivity(), "Your address is: " + address, Toast.LENGTH_SHORT).show();

                // make sure you close the gps after using it. Save user's battery power
                mGPSService.closeGPS();


            }
        });







        return rootView;
    }
}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接