高德地圖,仿餓了麼確認收貨地址頁(簡易版)

先看一下效果 android

其實高德地圖示例中心已經有不少現成的demo了,能夠根據項目需求,下載demo自行查看git

高德地圖android API地址:lbs.amap.com/api/android…api

高德地圖示例中心:lbs.amap.com/dev/demo數組

由於公司目前開發的項目,地圖模塊並非側重點,因此定位地址作得很簡易化。需求包括:定位當前位置,自動搜索周邊,搜索位置,選擇位置。下面會對代碼進行說明。安全

1.固然,首先得去高德地圖開放平臺中註冊帳號,建立應用bash

其中發佈版安全碼SHA1的獲取方式,請點擊高德地圖官方說明自行查看: lbs.amap.com/faq/android…

2.在app的build.gradle文件中引入地圖包,這邊我使用的是3d地圖,包括基礎地圖包、定位地圖包和搜索地圖包網絡

dependencies {
    //高德地圖 3D地圖
    implementation 'com.amap.api:location:latest.integration'
    implementation 'com.amap.api:search:latest.integration'
    implementation 'com.amap.api:3dmap:latest.integration'
}
複製代碼

3.在AndroidManifest.xml清單文件中,application裏面配置以下app

<!--高德地圖-->
        <meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="申請應用的Key值"/>
複製代碼

接下來就能夠正式開發了ide

4.頂部的透明浮窗效果shape_map_top_bg.xml,定義一個漸變的透明度背景函數

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <item android:gravity="center">
        <shape>
            <corners
                android:bottomLeftRadius="10dp"
                android:bottomRightRadius="10dp"/>
            <gradient
                android:angle="270"
                android:startColor="#6C000000"
                android:endColor="#00000000"
                android:type="linear" />
        </shape>
    </item>

</layer-list>
複製代碼

5.定義Activity的佈局文件activity_map_layout1.xml,頂部的搜索框佈局layout_edit,後面我會在代碼中動態設置其高度

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.amap.api.maps.MapView
            android:id="@+id/mMapView"
            android:layout_above="@+id/layout_bottom"
            android:layout_marginBottom="-20dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:paddingTop="25dp"
            android:background="@drawable/shape_map_top_bg">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <!--@mipmap/icon_map_top_bg-->
            <TextView
                android:id="@+id/tv_cancle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:gravity="center"
                android:textColor="@color/colorWhite"
                android:text="取消"
                android:textSize="16sp" />
            <TextView
                android:id="@+id/tv_confirm"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="13dp"
                android:paddingRight="13dp"
                android:paddingTop="8.5dp"
                android:paddingBottom="8.5dp"
                android:layout_centerVertical="true"
                android:gravity="center"
                android:layout_marginRight="15dp"
                android:layout_alignParentRight="true"
                android:textColor="@color/colorWhite"
                android:background="@drawable/btn_bg"
                android:text="肯定"
                android:textSize="16sp" />

        </RelativeLayout>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/layout_location"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:gravity="center"
            android:layout_above="@+id/layout_bottom"
            android:layout_alignParentRight="true"
            android:layout_marginRight="22dp"
            android:layout_marginBottom="43dp"
            android:background="@drawable/shape_map_location_bg">
            <TextView
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:background="@mipmap/icon_map_location"/>
        </LinearLayout>
        <LinearLayout
            android:id="@+id/layout_bottom"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:orientation="vertical"
            android:background="@drawable/shape_white_bg_top"
            android:layout_alignParentBottom="true"
            android:minWidth="280dp">
            
            <RelativeLayout
                android:id="@+id/layout_edit"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_margin="15dp"
                android:background="@drawable/search_map_bg"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/iv_search"
                    android:layout_width="15dp"
                    android:layout_height="15dp"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="15dp"
                    android:src="@mipmap/icon_map_search" />

                <AutoCompleteTextView
                    android:id="@+id/keyWord"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="10.5dp"
                    android:layout_toRightOf="@+id/iv_search"
                    android:background="@null"
                    android:layout_marginRight="15dp"
                    android:hint="搜索地點"
                    android:gravity="center_vertical"
                    android:singleLine="true"
                    android:textColor="@color/color_333333"
                    android:textColorHint="@color/color_666666"
                    android:textSize="17sp" />
            </RelativeLayout>
            <ListView
                android:id="@+id/listview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:divider="@null"
                android:scrollbars="none"
                android:fadingEdge="none"
                android:overScrollMode="never"
                android:cacheColorHint="#00000000"
                android:listSelector="@android:color/transparent" />
        </LinearLayout>
    </RelativeLayout>
</layout>

複製代碼

6.爲了防止地圖的搜索框,在觸發鍵盤後,由於高度不夠而被輸入法蓋住了,因此選擇動態控制底部搜索框的高度,代碼以下:

RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) bindingView.layoutBottom.getLayoutParams(); //取控件textView當前的佈局參數
        int height = DensityUtil.getDisplayHeight() / 5 * 3;
        linearParams.height = height;// 控件的高強制設成
        bindingView.layoutBottom.setLayoutParams(linearParams); //使設置好的佈局參數應用到控件
複製代碼

7.請求權限的相關代碼(作android6.0以上的適配)

//是否須要檢測後臺定位權限,設置爲true時,若是用戶沒有給予後臺定位權限會彈窗提示
    private boolean needCheckBackLocation = false;
    //若是設置了target > 28,須要增長這個權限,不然不會彈出"始終容許"這個選擇框
    private static String BACK_LOCATION_PERMISSION = "android.permission.ACCESS_BACKGROUND_LOCATION";
    /*************************************** 權限檢查******************************************************/

    /**
     * 須要進行檢測的權限數組
     */
    protected String[] needPermissions = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
//            Manifest.permission.READ_PHONE_STATE,
            BACK_LOCATION_PERMISSION
    };

    private static final int PERMISSON_REQUESTCODE = 0;

    /**
     * 判斷是否須要檢測,防止不停的彈框
     */
    private boolean isNeedCheck = true;
    
       @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT > 28
                && getApplicationContext().getApplicationInfo().targetSdkVersion > 28) {
            needPermissions = new String[]{
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.READ_PHONE_STATE,
                    BACK_LOCATION_PERMISSION
            };
            needCheckBackLocation = true;
        }
    }
    
        /**
     * 方法必須重寫
     */
    @Override
    protected void onResume() {
        try {
            super.onResume();
            bindingView.mMapView.onResume();
            if (Build.VERSION.SDK_INT >= 23) {
                if (isNeedCheck) {
                    checkPermissions(needPermissions);
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
    
       /**
     * @param
     * @since 2.5.0
     */
    @TargetApi(23)
    private void checkPermissions(String... permissions) {
        try {
            if (Build.VERSION.SDK_INT >= 23 && getApplicationInfo().targetSdkVersion >= 23) {
                List<String> needRequestPermissonList = findDeniedPermissions(permissions);
                if (null != needRequestPermissonList
                        && needRequestPermissonList.size() > 0) {
                    try {
                        String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
                        Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class, int.class});
                        method.invoke(this, array, 0);
                    } catch (Throwable e) {

                    }
                }
            }

        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 獲取權限集中須要申請權限的列表
     *
     * @param permissions
     * @return
     * @since 2.5.0
     */
    @TargetApi(23)
    private List<String> findDeniedPermissions(String[] permissions) {
        try {
            List<String> needRequestPermissonList = new ArrayList<String>();
            if (Build.VERSION.SDK_INT >= 23 && getApplicationInfo().targetSdkVersion >= 23) {
                for (String perm : permissions) {
                    if (checkMySelfPermission(perm) != PackageManager.PERMISSION_GRANTED
                            || shouldShowMyRequestPermissionRationale(perm)) {
                        if (!needCheckBackLocation
                                && BACK_LOCATION_PERMISSION.equals(perm)) {
                            continue;
                        }
                        needRequestPermissonList.add(perm);
                    }
                }
            }
            return needRequestPermissonList;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    private int checkMySelfPermission(String perm) {
        try {
            Method method = getClass().getMethod("checkSelfPermission", new Class[]{String.class});
            Integer permissionInt = (Integer) method.invoke(this, perm);
            return permissionInt;
        } catch (Throwable e) {
        }
        return -1;
    }

    private boolean shouldShowMyRequestPermissionRationale(String perm) {
        try {
            Method method = getClass().getMethod("shouldShowRequestPermissionRationale", new Class[]{String.class});
            Boolean permissionInt = (Boolean) method.invoke(this, perm);
            return permissionInt;
        } catch (Throwable e) {
        }
        return false;
    }

    /**
     * 檢測是否說有的權限都已經受權
     *
     * @param grantResults
     * @return
     * @since 2.5.0
     */
    private boolean verifyPermissions(int[] grantResults) {
        try {
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    return false;
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return true;
    }

    @TargetApi(23)
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions, int[] paramArrayOfInt) {
        try {
            if (Build.VERSION.SDK_INT >= 23) {
                if (requestCode == PERMISSON_REQUESTCODE) {
                    if (!verifyPermissions(paramArrayOfInt)) {
                        showMissingPermissionDialog();
                        isNeedCheck = false;
                    }
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 顯示提示信息
     *
     * @since 2.5.0
     */
    private void showMissingPermissionDialog() {
        try {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("提示");
            builder.setMessage("當前應用缺乏必要權限。\\n\\n請點擊\\\"設置\\\"-\\\"權限\\\"-打開所需權限");

            // 拒絕, 退出應用
            builder.setNegativeButton("取消",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                finish();
                            } catch (Throwable e) {
                                e.printStackTrace();
                            }
                        }
                    });

            builder.setPositiveButton("設置",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                startAppSettings();
                            } catch (Throwable e) {
                                e.printStackTrace();
                            }
                        }
                    });

            builder.setCancelable(false);

            builder.show();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 啓動應用的設置
     *
     * @since 2.5.0
     */
    private void startAppSettings() {
        try {
            Intent intent = new Intent(
                    Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivity(intent);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
複製代碼

8.顯示地圖的方式,請查看高德地圖官方說明 lbs.amap.com/api/android…

9.接下來我要說明的是我遇到的一種狀況:手機定位關閉後再次開啓,locationManager.getLastKnownLocation(provider)=null,我是這樣解決的:

首先,在oncreate初始化時,依然獲取最後一次定位的位置,並記下當前的最後一次位置lastLocation;

爲locationManager設置LocationListener監聽,包括GPS和NETWORK監聽;

一旦監聽到位置後,就會觸發onLocationChanged方法,這時候判斷lastLocation=null,就更新當前位置;

這樣就能夠解決位置關閉後開啓沒有辦法定位,又能防止搜索位置後,一直要定位到當前的這種狀況

好了,MapActivity的完整代碼以下:

public class MapActivity2 extends BaseActivity<AddressViewModel, ActivityMapLayout1Binding> implements LocationSource,
        AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener, PoiSearch.OnPoiSearchListener { // Inputtips.InputtipsListener


    //    private ListView listView;
//    private SegmentedGroup mSegmentedGroup;
//    private AutoCompleteTextView searchText;
    private AMap aMap;
    //    private MapView mapView;
    private OnLocationChangedListener mListener;
    private AMapLocationClient mlocationClient;
    private AMapLocationClientOption mLocationOption;

    private String[] items = {"", "學校", "樓宇", "商場"};

    private Marker locationMarker;

    private ProgressDialog progDialog = null;
    private GeocodeSearch geocoderSearch;

    private int currentPage = 0;// 當前頁面,從0開始計數
    private PoiSearch.Query query;// Poi查詢條件類
    private PoiSearch poiSearch;
    private List<PoiItem> poiItems;// poi數據

    private String searchType = items[0];
    private String searchKey = "";
    private LatLonPoint searchLatlonPoint;


    private List<PoiItem> resultData = new ArrayList<>();

    private MapSearchResultAdapter searchResultAdapter;

    private boolean isItemClickAction;

    private List<Tip> autoTips;
    private boolean isfirstinput = true;
    private PoiItem firstItem;


    //是否須要檢測後臺定位權限,設置爲true時,若是用戶沒有給予後臺定位權限會彈窗提示
    private boolean needCheckBackLocation = false;
    //若是設置了target > 28,須要增長這個權限,不然不會彈出"始終容許"這個選擇框
    private static String BACK_LOCATION_PERMISSION = "android.permission.ACCESS_BACKGROUND_LOCATION";
    /*************************************** 權限檢查******************************************************/

    /**
     * 須要進行檢測的權限數組
     */
    protected String[] needPermissions = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
//            Manifest.permission.READ_PHONE_STATE,
            BACK_LOCATION_PERMISSION
    };

    private static final int PERMISSON_REQUESTCODE = 0;

    /**
     * 判斷是否須要檢測,防止不停的彈框
     */
    private boolean isNeedCheck = true;

//    private String searchCity = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT > 28
                && getApplicationContext().getApplicationInfo().targetSdkVersion > 28) {
            needPermissions = new String[]{
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.READ_PHONE_STATE,
                    BACK_LOCATION_PERMISSION
            };
            needCheckBackLocation = true;
        }

        setContentView(R.layout.activity_map_layout1);
        showContentView();
//        if (getIntent() != null && getIntent().getExtras() != null){
//            searchCity = getIntent().getExtras().getString("searchCity");
//        }
        boolean is = isLocationEnabled();
        bindingView.mMapView.onCreate(savedInstanceState);
        init();
        initView();
    }

    private void initView() {
        bindingView.tvCancle.setOnClickListener(view -> {
            finish();
        });
        RelativeLayout.LayoutParams linearParams = (RelativeLayout.LayoutParams) bindingView.layoutBottom.getLayoutParams(); //取控件textView當前的佈局參數
        int height = DensityUtil.getDisplayHeight() / 5 * 3;
        linearParams.height = height;// 控件的高強制設成
        bindingView.layoutBottom.setLayoutParams(linearParams); //使設置好的佈局參數應用到控件


        bindingView.tvConfirm.setOnClickListener(view -> {
            PoiItem item = resultData.get(searchResultAdapter.getSelectedPosition());
            Intent intent = new Intent();
            intent.putExtra("PoiItem", item);
            setResult(1, intent);
            finish();
        });
        bindingView.layoutLocation.setOnClickListener(view -> {
            aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(lastLatLng, 16));
        });

        searchResultAdapter = new MapSearchResultAdapter(MapActivity2.this);
        bindingView.listview.setAdapter(searchResultAdapter);

        bindingView.listview.setOnItemClickListener(onItemClickListener);

        bindingView.keyWord.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String newText = s.toString().trim();
                if (newText.length() > 0) {
                    InputtipsQuery inputquery = new InputtipsQuery(newText, "");//searchCity
                    Inputtips inputTips = new Inputtips(MapActivity2.this, inputquery);
                    inputquery.setCityLimit(true);
                    inputTips.setInputtipsListener(inputtipsListener);
                    inputTips.requestInputtipsAsyn();
                }
//                else {
//                    doSearchQuery();
//                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

//        bindingView.keyWord.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//            @Override
//            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//                Log.i("MY", "setOnItemClickListener");
//                if (autoTips != null && autoTips.size() > position) {
//                    Tip tip = autoTips.get(position);
//                    searchPoi(tip);
//                }
//            }
//        });

        geocoderSearch = new GeocodeSearch(this);
        geocoderSearch.setOnGeocodeSearchListener(this);
        progDialog = new ProgressDialog(this);

//        hideSoftKey(bindingView.keyWord);
    }

    /**
     * 初始化
     */
    private void init() {
        if (aMap == null) {
            aMap = bindingView.mMapView.getMap();
            setUpMap();
        }

        aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition cameraPosition) {

            }

            @Override
            public void onCameraChangeFinish(CameraPosition cameraPosition) {
                searchLatlonPoint = new LatLonPoint(cameraPosition.target.latitude, cameraPosition.target.longitude);
                if (!isItemClickAction && !isInputKeySearch) {
                    geoAddress();
                    startJumpAnimation();
                }

                isInputKeySearch = false;
                isItemClickAction = false;
            }
        });

        aMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
            @Override
            public void onMapLoaded() {
                addMarkerInScreenCenter(null);
            }
        });
        setLocalLocation();
    }

    /**
     * 顯示當前定位
     */
    private LocationManager locationManager;

    private void setLocalLocation() {
        // 調用getSystemService()方法來獲取LocationManager對象
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        //locationManager.setTestProviderEnabled("gps", true);
        // 指定LocationManager的定位方法
//        String provider = LocationManager.GPS_PROVIDER;
        // 調用getLastKnownLocation()方法獲取當前的位置信息


        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, mLocationListener01);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, mLocationListener01);
        lastLocation = getLastKnownLocation();
        updateToNewLocation(lastLocation);
    }
    private Location lastLocation;

    // 設置監聽器,自動更新的最小時間爲間隔N秒(1秒爲1*1000,這樣寫主要爲了方便)或最小位移變化超過N米
    public final LocationListener mLocationListener01 = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
//            if (!isLocationEnabled()){
//                ToastUtil.showToast("位置信息關閉,請開啓");
//            }
            if (lastLocation == null) {//防止定位關閉開啓後定位不了
                lastLocation = location;
                updateToNewLocation(location);
            }
            //        Location location = locationManager.getLastKnownLocation(provider);
//            Location location = getLastKnownLocation();

        }


        @Override
        public void onProviderDisabled(String provider) {
//            updateToNewLocation(null);
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

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

    /**
     * 獲取數據和監聽器
     * 經過location獲取當前設備的具體位置
     *
     * @param location
     * @return
     */
    private void updateToNewLocation(Location location) {
        if (location != null) {
            LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());//構造一個位置
            lastLatLng = latLng;
            aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16));
        } else {
            LatLng latLng = new LatLng(39.904989, 116.405285);// 北京市經緯度
            lastLatLng = latLng;
            isInputKeySearch = false;
            isItemClickAction = false;
            aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16));
        }
    }

    /**
     * 判判定位服務是否開啓
     *
     * @param
     * @return true 表示開啓
     */
    public boolean isLocationEnabled() {
        int locationMode = 0;
        String locationProviders;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }


    private Location getLastKnownLocation() {
//        locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
        List<String> providers = locationManager.getProviders(true);
        Location bestLocation = null;
        for (String provider : providers) {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return null;
            }
            Location l = locationManager.getLastKnownLocation(provider);
            if (l == null) {
                continue;
            }
            if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
                // Found best last known location: %s", l); bestLocation = l; } } return bestLocation; } private LatLng lastLatLng; /** * 設置一些amap的屬性 */ private void setUpMap() { aMap.getUiSettings().setZoomControlsEnabled(false); aMap.setLocationSource(this);// 設置定位監聽 aMap.getUiSettings().setMyLocationButtonEnabled(true);// 設置默認定位按鈕是否顯示 aMap.setMyLocationEnabled(false);// 設置爲true表示顯示定位層並可觸發定位,false表示隱藏定位層並不可觸發定位,默認是false aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE); } /** * 方法必須重寫 */ @Override protected void onResume() { try { super.onResume(); bindingView.mMapView.onResume(); if (Build.VERSION.SDK_INT >= 23) { if (isNeedCheck) { checkPermissions(needPermissions); } } } catch (Throwable e) { e.printStackTrace(); } } /** * 方法必須重寫 */ @Override protected void onPause() { super.onPause(); bindingView.mMapView.onPause(); deactivate(); } /** * 方法必須重寫 */ @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); bindingView.mMapView.onSaveInstanceState(outState); } /** * 方法必須重寫 */ @Override public void onDestroy() { super.onDestroy(); bindingView.mMapView.onDestroy(); if (null != mlocationClient) { mlocationClient.onDestroy(); } locationManager.removeUpdates(mLocationListener01); // locationManager.setTestProviderEnabled(provider, false); } /** * 定位成功後回調函數 */ @Override public void onLocationChanged(AMapLocation amapLocation) { // Log.i("MY", "onLocationChanged"); if (mListener != null && amapLocation != null) { if (amapLocation != null && amapLocation.getErrorCode() == 0) { mListener.onLocationChanged(amapLocation); LatLng curLatlng = new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude()); searchLatlonPoint = new LatLonPoint(curLatlng.latitude, curLatlng.longitude); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(curLatlng, 16f)); isInputKeySearch = false; bindingView.keyWord.setText(""); } else { String errText = "定位失敗," + amapLocation.getErrorCode() + ": " + amapLocation.getErrorInfo(); Log.e("AmapErr", errText); } } } /** * 激活定位 */ @Override public void activate(OnLocationChangedListener listener) { mListener = listener; if (mlocationClient == null) { mlocationClient = new AMapLocationClient(this); mLocationOption = new AMapLocationClientOption(); //設置定位監聽 mlocationClient.setLocationListener(this); //設置爲高精度定位模式 mLocationOption.setOnceLocation(true); mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //設置定位參數 mlocationClient.setLocationOption(mLocationOption); // 此方法爲每隔固定時間會發起一次定位請求,爲了減小電量消耗或網絡流量消耗, // 注意設置合適的定位時間的間隔(最小間隔支持爲2000ms),而且在合適時間調用stopLocation()方法來取消定位請求 // 在定位結束後,在合適的生命週期調用onDestroy()方法 // 在單次定位狀況下,定位不管成功與否,都無需調用stopLocation()方法移除請求,定位sdk內部會移除 mlocationClient.startLocation(); } } /** * 中止定位 */ @Override public void deactivate() { mListener = null; if (mlocationClient != null) { mlocationClient.stopLocation(); mlocationClient.onDestroy(); } mlocationClient = null; } /** * 響應逆地理編碼 */ public void geoAddress() { // Log.i("MY", "geoAddress"+ searchLatlonPoint.toString()); // showDialog(); bindingView.keyWord.setText(""); if (searchLatlonPoint != null) { RegeocodeQuery query = new RegeocodeQuery(searchLatlonPoint, 200, GeocodeSearch.AMAP);// 第一個參數表示一個Latlng,第二參數表示範圍多少米,第三個參數表示是火系座標系仍是GPS原生座標系 geocoderSearch.getFromLocationAsyn(query); } } /** * 開始進行poi搜索 */ /** * 開始進行poi搜索 */ protected void doSearchQuery() { // Log.i("MY", "doSearchQuery"); currentPage = 0; query = new PoiSearch.Query(searchKey, searchType, "");// 第一個參數表示搜索字符串,第二個參數表示poi搜索類型,第三個參數表示poi搜索區域(空字符串表明全國) query.setCityLimit(true); query.setPageSize(20); query.setPageNum(currentPage); if (searchLatlonPoint != null) { poiSearch = new PoiSearch(this, query); poiSearch.setOnPoiSearchListener(this); poiSearch.setBound(new PoiSearch.SearchBound(searchLatlonPoint, 1000, true));// poiSearch.searchPOIAsyn(); } } @Override public void onRegeocodeSearched(RegeocodeResult result, int rCode) { // dismissDialog(); if (rCode == AMapException.CODE_AMAP_SUCCESS) { if (result != null && result.getRegeocodeAddress() != null && result.getRegeocodeAddress().getFormatAddress() != null) { String address = result.getRegeocodeAddress().getProvince() + result.getRegeocodeAddress().getCity() + result.getRegeocodeAddress().getDistrict() + result.getRegeocodeAddress().getTownship(); firstItem = new PoiItem("regeo", searchLatlonPoint, address, address); doSearchQuery(); } } else { // Toast.makeText(MapActivity2.this, "error code is " + rCode, Toast.LENGTH_SHORT).show(); } } @Override public void onGeocodeSearched(GeocodeResult result, int rCode) { if (rCode == AMapException.CODE_AMAP_SUCCESS) { if (result != null && result.getGeocodeAddressList() != null && result.getGeocodeAddressList() != null) { String address = result.getGeocodeAddressList().get(0).getProvince() + result.getGeocodeAddressList().get(0).getCity() + result.getGeocodeAddressList().get(0).getDistrict() + result.getGeocodeAddressList().get(0).getTownship(); firstItem = new PoiItem("regeo", searchLatlonPoint, address, address); doSearchQuery(); } } else { // Toast.makeText(MapActivity2.this, "error code is " + rCode, Toast.LENGTH_SHORT).show(); } } /** * POI搜索結果回調 * * @param poiResult 搜索結果 * @param resultCode 錯誤碼 */ @Override public void onPoiSearched(PoiResult poiResult, int resultCode) { if (resultCode == AMapException.CODE_AMAP_SUCCESS) { if (poiResult != null && poiResult.getQuery() != null) { if (poiResult.getQuery().equals(query)) { poiItems = poiResult.getPois(); if (poiItems != null && poiItems.size() > 0) { updateListview(poiItems); } else { // Toast.makeText(MapActivity2.this, "無搜索結果", Toast.LENGTH_SHORT).show(); } } } else { // Toast.makeText(MapActivity2.this, "無搜索結果", Toast.LENGTH_SHORT).show(); } } } /** * 更新列表中的item * * @param poiItems */ private void updateListview(List<PoiItem> poiItems) { resultData.clear(); searchResultAdapter.setSelectedPosition(0); resultData.add(firstItem); resultData.addAll(poiItems); searchResultAdapter.setData(resultData); searchResultAdapter.notifyDataSetChanged(); } @Override public void onPoiItemSearched(PoiItem poiItem, int i) { } AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position != searchResultAdapter.getSelectedPosition()) { PoiItem poiItem = (PoiItem) searchResultAdapter.getItem(position); LatLng curLatlng = new LatLng(poiItem.getLatLonPoint().getLatitude(), poiItem.getLatLonPoint().getLongitude()); isItemClickAction = true; aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(curLatlng, 16f)); searchResultAdapter.setSelectedPosition(position); searchResultAdapter.notifyDataSetChanged(); } } }; public void showDialog() { progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progDialog.setIndeterminate(false); progDialog.setCancelable(true); progDialog.setMessage("正在加載..."); progDialog.show(); } public void dismissDialog() { if (progDialog != null) { progDialog.dismiss(); } } private void addMarkerInScreenCenter(LatLng locationLatLng) { LatLng latLng = aMap.getCameraPosition().target; Point screenPosition = aMap.getProjection().toScreenLocation(latLng); locationMarker = aMap.addMarker(new MarkerOptions() .anchor(0.5f, 0.5f) .icon(BitmapDescriptorFactory.fromResource(R.mipmap.purple_pin))); //設置Marker在屏幕上,不跟隨地圖移動 locationMarker.setPositionByPixels(screenPosition.x, screenPosition.y); locationMarker.setZIndex(1); } /** * 屏幕中心marker 跳動 */ public void startJumpAnimation() { if (locationMarker != null) { //根據屏幕距離計算須要移動的目標點 final LatLng latLng = locationMarker.getPosition(); Point point = aMap.getProjection().toScreenLocation(latLng); point.y -= dip2px(this, 125); LatLng target = aMap.getProjection() .fromScreenLocation(point); //使用TranslateAnimation,填寫一個須要移動的目標點 Animation animation = new TranslateAnimation(target); animation.setInterpolator(new Interpolator() { @Override public float getInterpolation(float input) { // 模擬重加速度的interpolator if (input <= 0.5) { return (float) (0.5f - 2 * (0.5 - input) * (0.5 - input)); } else { return (float) (0.5f - Math.sqrt((input - 0.5f) * (1.5f - input))); } } }); //整個移動所須要的時間 animation.setDuration(600); //設置動畫 locationMarker.setAnimation(animation); //開始動畫 locationMarker.startAnimation(); } else { Log.e("ama", "screenMarker is null"); } } //dip和px轉換 private static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } private void searchAllPoi(Tip result) { isInputKeySearch = true; inputSearchKey = result.getName();//getAddress(); // + result.getRegeocodeAddress().getCity() + result.getRegeocodeAddress().getDistrict() + result.getRegeocodeAddress().getTownship(); searchLatlonPoint = result.getPoint(); firstItem = new PoiItem("tip", searchLatlonPoint, inputSearchKey, result.getAddress()); firstItem.setCityName(result.getDistrict()); firstItem.setAdName(""); searchResultAdapter.setSelectedPosition(0); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(searchLatlonPoint.getLatitude(), searchLatlonPoint.getLongitude()), 16f)); // hideSoftKey(bindingView.keyWord); doSearchQuery(); } Inputtips.InputtipsListener inputtipsListener = new Inputtips.InputtipsListener() { @Override public void onGetInputtips(List<Tip> list, int rCode) { if (rCode == AMapException.CODE_AMAP_SUCCESS) {// 正確返回 autoTips = list; resultData.clear(); if (autoTips != null && autoTips.size() != 0) { searchAllPoi(autoTips.get(0)); } // for (int i = 0; i < autoTips.size(); i++){ // Tip tip = autoTips.get(i); // searchAllPoi(autoTips.get(0)); // } // List<String> listString = new ArrayList<String>(); // for (int i = 0; i < list.size(); i++) { // listString.add(list.get(i).getName()); // } // ArrayAdapter<String> aAdapter = new ArrayAdapter<String>( // getApplicationContext(), // R.layout.route_inputs, listString); // bindingView.keyWord.setAdapter(aAdapter); // aAdapter.notifyDataSetChanged(); // if (isfirstinput) { // isfirstinput = false; // bindingView.keyWord.showDropDown(); // } } else { // Toast.makeText(MapActivity2.this, "erroCode " + rCode , Toast.LENGTH_SHORT).show(); } } }; private boolean isInputKeySearch; private String inputSearchKey; private void searchPoi(Tip result) { isInputKeySearch = true; inputSearchKey = result.getName();//getAddress(); // + result.getRegeocodeAddress().getCity() + result.getRegeocodeAddress().getDistrict() + result.getRegeocodeAddress().getTownship(); searchLatlonPoint = result.getPoint(); firstItem = new PoiItem("tip", searchLatlonPoint, inputSearchKey, result.getAddress()); firstItem.setCityName(result.getDistrict()); firstItem.setAdName(""); resultData.clear(); searchResultAdapter.setSelectedPosition(0); aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(searchLatlonPoint.getLatitude(), searchLatlonPoint.getLongitude()), 16f)); // hideSoftKey(bindingView.keyWord); doSearchQuery(); } private void hideSoftKey(View view) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, InputMethodManager.SHOW_FORCED); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } /** * @param * @since 2.5.0 */ @TargetApi(23) private void checkPermissions(String... permissions) { try { if (Build.VERSION.SDK_INT >= 23 && getApplicationInfo().targetSdkVersion >= 23) { List<String> needRequestPermissonList = findDeniedPermissions(permissions); if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) { try { String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]); Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class, int.class}); method.invoke(this, array, 0); } catch (Throwable e) { } } } } catch (Throwable e) { e.printStackTrace(); } } /** * 獲取權限集中須要申請權限的列表 * * @param permissions * @return * @since 2.5.0 */ @TargetApi(23) private List<String> findDeniedPermissions(String[] permissions) { try { List<String> needRequestPermissonList = new ArrayList<String>(); if (Build.VERSION.SDK_INT >= 23 && getApplicationInfo().targetSdkVersion >= 23) { for (String perm : permissions) { if (checkMySelfPermission(perm) != PackageManager.PERMISSION_GRANTED || shouldShowMyRequestPermissionRationale(perm)) { if (!needCheckBackLocation && BACK_LOCATION_PERMISSION.equals(perm)) { continue; } needRequestPermissonList.add(perm); } } } return needRequestPermissonList; } catch (Throwable e) { e.printStackTrace(); } return null; } private int checkMySelfPermission(String perm) { try { Method method = getClass().getMethod("checkSelfPermission", new Class[]{String.class}); Integer permissionInt = (Integer) method.invoke(this, perm); return permissionInt; } catch (Throwable e) { } return -1; } private boolean shouldShowMyRequestPermissionRationale(String perm) { try { Method method = getClass().getMethod("shouldShowRequestPermissionRationale", new Class[]{String.class}); Boolean permissionInt = (Boolean) method.invoke(this, perm); return permissionInt; } catch (Throwable e) { } return false; } /** * 檢測是否說有的權限都已經受權 * * @param grantResults * @return * @since 2.5.0 */ private boolean verifyPermissions(int[] grantResults) { try { for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { return false; } } } catch (Throwable e) { e.printStackTrace(); } return true; } @TargetApi(23) public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) { try { if (Build.VERSION.SDK_INT >= 23) { if (requestCode == PERMISSON_REQUESTCODE) { if (!verifyPermissions(paramArrayOfInt)) { showMissingPermissionDialog(); isNeedCheck = false; } } } } catch (Throwable e) { e.printStackTrace(); } } /** * 顯示提示信息 * * @since 2.5.0 */ private void showMissingPermissionDialog() { try { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("提示"); builder.setMessage("當前應用缺乏必要權限。\\n\\n請點擊\\\"設置\\\"-\\\"權限\\\"-打開所需權限");

            // 拒絕, 退出應用
            builder.setNegativeButton("取消",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                finish();
                            } catch (Throwable e) {
                                e.printStackTrace();
                            }
                        }
                    });

            builder.setPositiveButton("設置",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                startAppSettings();
                            } catch (Throwable e) {
                                e.printStackTrace();
                            }
                        }
                    });

            builder.setCancelable(false);

            builder.show();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 啓動應用的設置
     *
     * @since 2.5.0
     */
    private void startAppSettings() {
        try {
            Intent intent = new Intent(
                    Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivity(intent);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

複製代碼
相關文章
相關標籤/搜索