无法通过服务获取位置 (LocationManager)

Not able to get location with Service (LocationManager)

我真的遇到麻烦了。尝试每 3 秒通过后台服务获取纬度和经度,但是当我在模拟器的扩展控件中单击发送纬度和经度时,我只能写入一些数据,因此 phone 和模拟器都无法正常工作。下面是我的代码,如果有人能帮助我,那就太棒了。谢谢!

服务

public class GPSService extends Service {


    private static final String TAG = "GpsService";
    private LocationListener locationListener;
    private LocationManager locationManager;


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

    @Override
    public void onCreate() {

        locationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                Intent i = new Intent("location_update");
                i.putExtra("latExtra",location.getLatitude());
                i.putExtra("lonExtra",location.getLongitude());
                sendBroadcast(i);
                Log.i(TAG, "onLocationChanged: extras lat lon"+location.getLatitude()+" "+location.getLongitude());
            }

            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {

            }

            @Override
            public void onProviderEnabled(String s) {

            }

            @Override
            public void onProviderDisabled(String s) {
                Log.i(TAG, "onProviderDisabled: DISABLED");
                Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(i);
            }
        };

        locationManager =(LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);

        Criteria c = new Criteria();
        String provider =locationManager.getBestProvider(c,true);
        Log.i(TAG, "onCreate: bestProvider "+provider);

        //noinspection MissingPermission
        locationManager.requestLocationUpdates(provider,2000,0,locationListener);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (locationManager != null){
            Log.i(TAG, "onDestroy: Location manager nije null i brisem");
            //noinspection MissingPermission
            locationManager.removeUpdates(locationListener);
        }

    }
}

主要活动

    private final String TAG = "Main";
    ...
    BroadcastReceiver broadcastReciever;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //setStatusBarTranslucent(false);


        if(!runtimePermisions()){
            startLocationUpdate();}
...

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //stopService();
                if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                    //REQUEST PERMISSION
                    Log.i(TAG, "onClick: NO PERMISION");
                } else {
                    Log.i(TAG, "onClick: got permision");
                }
...
    }
    public void startLocationUpdate(){
        Intent i = new Intent(this,GPSService.class);
        startService(i);
        Log.i(TAG, "startLocationUpdate: Pokrenuo sam service");
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (broadcastReciever == null){
            broadcastReciever = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {

                    lat = (Double) intent.getExtras().get("latExtra");
                    lon = (Double) intent.getExtras().get("lonExtra");

                    Log.i(TAG, "onReceive: lat lon "+lat+" "+lon);
                }
            };
        }
        registerReceiver(broadcastReciever,new IntentFilter("location_update"));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (broadcastReciever!=null){
            unregisterReceiver(broadcastReciever);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 100) {
                if (grantResults [0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED){
                    startLocationUpdate();
                }else{
                    runtimePermisions();}
            }

    }


    private boolean runtimePermisions() {
        if (Build.VERSION.SDK_INT >= 23 &&ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
            requestPermissions(new String[]{
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,

            },100);
            return true;
        }
        return false;
    }

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.digiart.yoweather">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SettingsActivity"
            android:theme="@style/SettingsTheme"></activity>
        <service android:name=".Gps.GPSService"/>
    </application>

</manifest>

再次......任何帮助都会很棒!谢谢 :D

正如 K. Sopheak 所说,获取位置可能需要一段时间。来自文档:

It may take a while to receive the first location update. If an immediate location is required, applications may use the getLastKnownLocation(String) method.

因此,您可以尝试在服务启动时使用 getLastKnownLocation(String) 获取最后一个已知位置,并假设它存在,以与位置更新相同的方式广播它。但请记住,最后已知的位置可能已过时。根据您使用的内容,该位置可能会或可能不会被接受。

另外,顺便说一句,有几点想法:

  1. 你说的是 3 秒,但代码使用了 2,000 毫秒 - 这只是一个错字吗?

  2. 位置更新的频率是 最短 次 - 您不能保证经常获得更新。根据文档:

    The location update interval can be controlled using the minTime parameter. The elapsed time between location updates will never be less than minTime, although it can be more depending on the Location Provider implementation and the update interval requested by other applications.

  3. 您是否有任何特殊原因需要以如此高的频率更新位置?获取位置可能会消耗大量电池电量,特别是考虑到您正在请求 FINE 和 COARSE 位置权限,因此如此频繁地请求它可能会极大地消耗设备电池寿命。鉴于代码在服务中 运行ning 并且因此将继续 运行 即使应用程序在后台或用户在 activity 而不是需要位置数据。同样,来自文档:

    Choosing a sensible value for minTime is important to conserve battery life. Each location update requires power from GPS, WIFI, Cell and other radios. Select a minTime value as high as possible while still providing a reasonable user experience. If your application is not in the foreground and showing location to the user then your application should avoid using an active provider (such as NETWORK_PROVIDER or GPS_PROVIDER), but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) or greater. If your application is in the foreground and showing location to the user then it is appropriate to select a faster update interval.

  4. Google 建议使用 Google Play services location APIs 而不是 Android 框架位置 API:

    The Google Play services location APIs are preferred over the Android framework location APIs (android.location) as a way of adding location awareness to your app. If you are currently using the Android framework location APIs, you are strongly encouraged to switch to the Google Play services location APIs as soon as possible.