【问题标题】:How to get location in android 8.0?如何在 android 8.0 中获取位置?
【发布时间】:2023-04-09 14:03:01
【问题描述】:

我想在应用程序运行时在 Android 8.0+ 中获取当前位置的经度和纬度,并且我不想像在后台服务中那样显示通知。

我之前在 8.0 以下的 android 中使用后台定位服务,但在 8.0 中我们需要显示通知。

【问题讨论】:

    标签: android notifications location android-8.0-oreo


    【解决方案1】:

    使用作业调度器,它将在空闲状态下工作

      if(Build.VERSION.SDK_INT>= 21)
                {
                    jobScheduler = (JobScheduler) (getActivity()).getSystemService(JOB_SCHEDULER_SERVICE);
                    ComponentName componentName = new ComponentName((getActivity()), MyBackgroundService.class);
                    JobInfo jobInfo = new JobInfo.Builder(1, componentName)
                            .setPeriodic(100).build();
                    Toast.makeText(getActivity(), "Service started!", Toast.LENGTH_SHORT).show();
                    jobScheduler.schedule(jobInfo);
                }
    

    MyBackgroundService.class

    public class MyBackgroundService extends JobService {
    
    private JobParameters params;
    private myTask doThisTask;
    boolean isGPSEnable = false;
    boolean isNetworkEnable = false;
    double latitude,longitude;
    LocationManager locationManager;
    Location location;
    private String UserIDForToken;
    private WeakReference<Context> cReference;
    private RequestQueue requestQueue;
    private LocationListener locationListener;
    ConnectivityManager connectivityManager;
    
    
    @Override
    public boolean onStartJob(JobParameters params) {
        Log.d("called","onStartJob");
        this.params = params;
        cReference = new WeakReference<Context>(MyBackgroundService.this);
        requestQueue = Volley.newRequestQueue(cReference.get());
        doThisTask = new myTask();
        doThisTask.execute();
        return false;
    }
    
    @Override
    public boolean onStopJob(JobParameters params) {
        if (doThisTask != null)
            doThisTask.cancel(true);
        return false;
    }
    
    private class myTask extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected Void doInBackground(Void... params) {
    
            Log.d("called","doInBack");
            Log.d("called","done");
    
            /** displaying a toast ... **/
            Handler handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
    
                @Override
                public void run() {
                    Log.d("called","handle.post");
                    Toast.makeText(getApplicationContext(), "DONE !", Toast.LENGTH_SHORT).show();
                    fn_getlocation();
                }
            });
            return null;
        }
    
        @Override
        protected void onPostExecute(Void aVoid) {
            //jobFinished(params, false);
            super.onPostExecute(aVoid);
        }
    }
    
    
    @SuppressLint("MissingPermission")
    private void fn_getlocation(){
        Log.d("called","fn_getlocation");
        locationManager = (LocationManager)getApplicationContext().getSystemService(LOCATION_SERVICE);
        isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    
        if (!isGPSEnable && !isNetworkEnable){
    
        }else {
    
    
            if (isGPSEnable){
                location = null;
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
                    @Override
                    public void onLocationChanged(Location location) {
                    }
    
                    @Override
                    public void onStatusChanged(String provider, int status, Bundle extras) {
    
                    }
    
                    @Override
                    public void onProviderEnabled(String provider) {
    
                    }
    
                    @Override
                    public void onProviderDisabled(String provider) {
    
                    }
                });
                if (locationManager!=null){
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    if (location!=null){
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        fn_update(location);
                    }
                }
            }
    
    
        }
    
    }
    private void fn_update(Location location){
        if(haveNetwork()) {
          // do your job here
        }else if(!haveNetwork())
        {
           Log.d("network not there","what");
        }
    
    }
    
    
    
    
    
    private boolean haveNetwork(){
        boolean have_WIFI=false;
        boolean have_MOBILE_DATA= false;
    
        connectivityManager = (ConnectivityManager) cReference.get().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] networkInfos= connectivityManager.getAllNetworkInfo();
    
    
        for(NetworkInfo info:networkInfos)
        {
            if(info.getTypeName().equalsIgnoreCase("WIFI"))
                if(info.isConnected())
                    have_WIFI = true;
            if(info.getTypeName().equalsIgnoreCase("MOBILE"))
                if(info.isConnected())
                    have_MOBILE_DATA = true;
        }
        return have_MOBILE_DATA || have_WIFI;
    }
    

    }

    【讨论】:

      【解决方案2】:

      我假设您所说的通知是此处提示位置许可的对话框。

      要在 Android 8.0 中获取用户位置,您可以使用 Google 的 FusedLocationProviderClient

      在此之前,您需要获得用户的位置许可。 请按照以下步骤操作:

      在您的 AndroidManifest.xml 中添加权限

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

      向用户请求位置

      //This can be any integer you want, just make sure they are same while requesting and handling the result
      val REQUEST_LOCATION_PERMISSION_CODE = 100
      
      ActivityCompat.requestPermissions(this@SplashActivity,
                          listOf(Manifest.permission.ACCESS_FINE_LOCATION).toTypedArray(),
                          1)
      

      重写onRequestPermissionsResult函数来获取权限对话结果

      override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults)
              if(requestCode == REQUEST_LOCATION_PERMISSION_CODE){
                  if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      //Permission Granted. Yeah!
                  }else{
                      //Permission Denied. You might need to show a dialog to let user understand why u need the location, or disable any features that need location
                  }
              }
          }
      

      实现该库,在应用级 gradle 中添加以下行:

      implementation 'com.google.android.gms:play-services-location:15.0.1'
      

      然后,在要获取位置的activity/fragment中,

      LocationServices.getFusedLocationProviderClient(this)
                      .lastLocation
                      .addOnSuccessListener { location->
                          Log.i("LocationLatitude",location.latitude.toString())
                          Log.i("LocationLongitude",location.longitude.toString())
                      }
                      .addOnFailureListener { error->
                          error.printStackTrace()
                      }
      

      如果您想在应用程序中重复使用位置,您实际上可以将 LocationServices.getFusedLocationProviderClient(this) 声明为全局变量或使用数据注入。

      如果您更喜欢快捷方式而不是原生方式,可以查看 DexterEasyPermissions 等库

      【讨论】:

      • 我说的是你必须显示的通知,就像这个应用在通知抽屉中使用 GPS 一样
      猜你喜欢
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 2013-09-20
      • 2018-08-09
      • 2023-03-25
      相关资源
      最近更新 更多