Android LocationManager、あなたの経緯を報告します!

22226 ワード

黙氏は、「Androidが開発されたとき、ユーザーの地理的位置を得る必要があるのはますます簡単になっており、様々な地図SDKが正確な位置決め方法を提供している」と話した.しかし、もしあなたのニーズがユーザーの都市に曖昧に位置づけるだけであれば、システムAPIは完全にあなたのニーズを満たすことができ、この時に地図SDKを統合するのは重すぎると感じます.ネット上でシステムAPIを使って位置づける文章は比較的早いし、Android 6.0バージョンは危険権限の動的検証が入っているので、直接持ってきて使えるツール類はほとんどないので、車輪を組み立てて使うしかありません.技術的な含有量はありません.大牛は軽く撮ります.
動図鎮楼
Android定位執事:LocationManager
きほんしよう
  • LocationManager
  • を取得
  • 測位サービス(GPS,WIFI,基地局)が利用可能か否かを判断する
  • .
  • 位置決め傍受を設置し、経緯度
  • を取得する.
    public void initLocation(Context context){
      //    LocationManager
      mLocationManager = (LocationManager) context
                    .getSystemService(Context.LOCATION_SERVICE);
      //           ,     GPS   。
      if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                        0, 0, new LocationListener() {
                    @Override
                    public void onLocationChanged(Location location) {
                        //            
                        location.getLatitude();//  
                        location.getLongitude();//  
                    }
    
                    @Override
                    public void onStatusChanged(String provider, int status, Bundle extras) {
                        //      
                        //provider:     (NetWork,Gps )
                        //status: 3   ,      ,     ,    
                        //extras:            
                    }
    
                    @Override
                    public void onProviderEnabled(String provider) {
                        //      
                    }
    
                    @Override
                    public void onProviderDisabled(String provider) {
                        //      
                    }
                });
            } 
    
    }

    必要な権限
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    基本的には、これらの関数を使えば緯度が得られるのですが、超簡単なのではないでしょうか.ここでネットワークを使って位置決めをするのは、位置決め速度が比較的速いため、室内でも使用できます.精度はgps位置決めほど高くありませんが、私たちの精度は都市レベルにしかないので、この誤差は完全に受け入れられます.
    位置決めツールクラスパッケージ:LocationUtils
    LocationUtilsクラスコード:
    package cn.motalks.mtdc.utils;
    
    import android.Manifest;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.util.Log;
    
    /**
     * Created by MoLin on 16/9/25.
     */
    public class LocationUtils {
    
        private volatile static LocationUtils uniqueInstance;
        private LocationHelper mLocationHelper;
        private MyLocationListener myLocationListener;
        private LocationManager mLocationManager;
        private Context mContext;
    
        private LocationUtils(Context context) {
            mContext = context;
            mLocationManager = (LocationManager) context
                    .getSystemService( Context.LOCATION_SERVICE );
        }
    
        //  Double CheckLock(DCL)    
        public static LocationUtils getInstance(Context context) {
            if (uniqueInstance == null) {
                synchronized (LocationUtils.class) {
                    if (uniqueInstance == null) {
                        uniqueInstance = new LocationUtils( context );
                    }
                }
            }
            return uniqueInstance;
        }
    
        /**
         *        
         * @param locationHelper         
         */
        public void initLocation(LocationHelper locationHelper) {
            Location location = null;
            mLocationHelper = locationHelper;
            if (myLocationListener == null) {
                myLocationListener = new MyLocationListener();
            }
            //       ,      ,         ,     。       code  。
            if ( Build.VERSION.SDK_INT >= 23 &&
                    ActivityCompat.checkSelfPermission( mContext, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission( mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return  ;
            }
            if (mLocationManager.isProviderEnabled( LocationManager.NETWORK_PROVIDER )) {
                location = mLocationManager.getLastKnownLocation( LocationManager.NETWORK_PROVIDER );
                Log.e("MoLin", "LocationManager.NETWORK_PROVIDER");
                if (location != null) {
                    locationHelper.UpdateLastLocation(location);
                }
                mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                        0, 0, myLocationListener);
            } else {
                Log.e("MoLin", "LocationManager.GPS_PROVIDER");
                location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                if (location != null) {
                    locationHelper.UpdateLastLocation(location);
                }
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                        1000, 50, myLocationListener);
            }
        }
    
        private class MyLocationListener implements LocationListener {
            //              
            @Override
            public void onStatusChanged(String provider, int status,
                                        Bundle extras) {
                Log.e("MoLin", "onStatusChanged!");
                if (mLocationHelper != null) {
                    mLocationHelper.UpdateStatus(provider, status, extras);
                }
            }
            //              
            @Override
            public void onProviderEnabled(String provider) {
                Log.e("MoLin", "onProviderEnabled!" + provider);
            }
            //              
            @Override
            public void onProviderDisabled(String provider) {
                Log.e("MoLin", "onProviderDisabled!" + provider);
            }
            //            ,  Provider       ,       
            @Override
            public void onLocationChanged(Location location) {
                Log.e("MoLin", "onLocationChanged!");
                if (mLocationHelper != null) {
                    mLocationHelper.UpdateLocation(location);
                }
            }
        }
        //       
        public void removeLocationUpdatesListener() {
            //       ,      
            if ( Build.VERSION.SDK_INT >= 23 &&
                    ActivityCompat.checkSelfPermission( mContext, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission( mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return  ;
            }
            if (mLocationManager != null) {
                mLocationManager.removeUpdates(myLocationListener);
            }
        }
    }

    LocationUtilsクラスの使用
    ここでの動的権限管理には,いずれも米同級生がカプセル化したEasyPermissionsExクラスが用いられている.(このクラスは以下で詳しく説明します)
    package cn.motalks.mtdc.ui;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.location.GpsStatus;
    import android.location.Location;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    import cn.motalks.mtdc.R;
    import cn.motalks.mtdc.utils.EasyPermissionsEx;
    import cn.motalks.mtdc.utils.LocationHelper;
    import cn.motalks.mtdc.utils.LocationUtils;
    
    /**
     * Created by MoLin on 16/9/25.
     */
    public class LocationTest2Activity extends Activity {
    
        private TextView mLatitudeView;
        private TextView mLongtitudeView;
        private TextView mWeatherView;
        private Button mButton;
        private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
        private static final int RC_SETTINGS_SCREEN = 2;
        private String[] mNeedPermissionsList = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            setContentView(R.layout.location_text_activity);
            initView();
            super.onCreate(savedInstanceState);
        }
    
        private void initView() {
            mLatitudeView = (TextView) findViewById(R.id.location_latitude);
            mLongtitudeView = (TextView) findViewById(R.id.location_longtitude);
            mWeatherView = (TextView) findViewById(R.id.weather_info_tv);
            mButton = (Button) findViewById(R.id.location_button);
    
            mButton.setOnClickListener( new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //     EasyPermissionsEx           
                    if (EasyPermissionsEx.hasPermissions(LocationTest2Activity.this, mNeedPermissionsList)) {
                        initLocation();
                    } else {
                        EasyPermissionsEx.requestPermissions(LocationTest2Activity.this, "               ", PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION, mNeedPermissionsList);
                    }
                }
            });
        }
    
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            switch (requestCode) {
                case PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION: {
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        Log.e("MoLin", "     !");
                        initLocation();
                    } else {
                        if (EasyPermissionsEx.somePermissionPermanentlyDenied(this, mNeedPermissionsList)) {
                            EasyPermissionsEx.goSettings2Permissions(this, "               ,        ,         "
                                    , "   ", RC_SETTINGS_SCREEN);
                        }
                    }
                }
                break;
    
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RC_SETTINGS_SCREEN) {
                Toast.makeText(this, "settings", Toast.LENGTH_LONG).show();
            }
        }
    
        private void initLocation() {
            LocationUtils.getInstance(LocationTest2Activity.this).initLocation( new LocationHelper() {
                @Override
                public void UpdateLocation(Location location) {
                    Log.e("MoLin", "location.getLatitude():" + location.getLatitude());
                    mLatitudeView.setText(location.getLatitude() + "");
                    mLongtitudeView.setText(location.getLongitude() + "");
                }
    
                @Override
                public void UpdateStatus(String provider, int status, Bundle extras) {
                }
    
                @Override
                public void UpdateGPSStatus(GpsStatus pGpsStatus) {
    
                }
    
                @Override
                public void UpdateLastLocation(Location location) {
                    Log.e("MoLin", "UpdateLastLocation_location.getLatitude():" + location.getLatitude());
                    mLatitudeView.setText(location.getLatitude() + "");
                    mLongtitudeView.setText(location.getLongitude() + "");
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            //             
            LocationUtils.getInstance(LocationTest2Activity.this).removeLocationUpdatesListener();
            super.onDestroy();
        }
    }
    

    動的権限の構成
    Android 6.0およびそれ以上のバージョンでは、システムはAPPのインストール時にすべての一般的な権限を許可し、危険な権限は使用時に動的にユーザーに許可する必要があります.これにより、Androidの権限管理がより柔軟になり、ユーザーは必要に応じて設定アプリケーションでアプリケーションの各危険権限に異なる権限を付与することができます.Androidシステムの権限管理が何人に突っ込まれたのか分からないが、この改善は間違いなくプラス点だ.
    危険権限の紹介
    次の図は、すべての危険権限のリストです.使用時にユーザーに動的に権限を与える必要があります.各対応する危険権限は1つの権限グループに対応し、危険権限を申請した場合、ユーザーの許可を得た後、対応する権限グループの他の権限を得ることができます.例えば、メールを読む権限を申請し、ユーザーが許可をクリックすると、メールを書く権限を申請すると、ダイアログボックスをポップアップしてユーザーに確認を要求することなく、すぐに許可されます.
    動的権限管理ツールクラス
    Googleは以前githubでEasyPermissionsをオープンソースしていましたが、なぜ権限が必要なのか説明するときにダイアログボックスをポップアップしてユーザー操作をブロックし、ユーザーが「禁止された後、質問しない」とチェックした後もダイアログボックスをポップアップして権限を要求し、ユーザー体験はあまりよくありません.EasyPermissionsExのある国人はEasyPermissionsパッケージのクラスライブラリに基づいて、使用説明は「Androidの公式開発指導-ランタイム権限の解読」を参照してください.
    Demo GitHubアドレス
    https://github.com/apkcoder/AndroidLocationUtils
    三太り:図を見て話す
    本稿はMoTalksに先発する.cn