Integrate Gaode map SDK in Android to realize map positioning and navigation functions (2)

We followed the previous article and continued to implement the SDK integrated with Gaode map in android to realize the functions of map positioning, search and navigation

How to realize the map on the mobile phone?

1. Configure the permission application in AndroidManifest

You can refer to the official document

  <!--允许访问网络,必选权限-->
    <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" />

    <!--允许获取设备和运营商信息,用于问题排查和网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <!--允许获取网络状态,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!--允许获取wifi网络信息,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <!--允许获取wifi状态改变,用于网络定位(无gps情况下的定位),若需网络定位功能则必选-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

    <!--后台获取位置信息,若需后台定位或持续导航则必选-->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <!--用于申请调用A-GPS模块,卫星定位加速-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />

    <!--允许写入扩展存储,用于写入缓存定位数据-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!--用于用户链接蓝牙时,在导航组件页面的蓝牙连接提醒,建立链接后开发者可选用蓝牙通道进行tts播报-->
    <uses-permission android:name="android.permission.BLUETOOTH" />

    <!--用与导航状态中保持屏幕常亮-->
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <!--允许写设备缓存,用于问题排查-->
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

    <!--允许读设备等信息,用于问题排查-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

After android6.0, you need to dynamically apply for permission. I won’t explain it in detail here.

Set the key of Gaode map

Add the previous key on the high developer platform to the application tag of the androidMainfest file, the code is as follows

  <meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="这个地方就是你之前申请的key" />

My key is ba63b...
insert image description here

Initialize the map control

First, create a new Activiy that hosts the map, and then initialize the MapView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.GaodeMapActivity"
    android:orientation="vertical">
    
     <com.amap.api.maps.MapView
        android:id="@+id/gaode_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="16dp"
        tools:layout_editor_absoluteY="39dp">
     </com.amap.api.maps.MapView>

</LinearLayout>

Then initialize the map empty in the Activity, here you need to understand that the Activity life cycle is bound to this map

public class GaodeMapActivity extends AppCompatActivity {
    
    
    private static final String TAG = "GaodeMapActivity";
    private MapView mapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gaode_map);
        // 这一步操作就设置高德地图中的隐私合规,不然可能会出现地图无法正确加载的问题
        MapsInitializer.updatePrivacyShow(this,true,true);
        MapsInitializer.updatePrivacyAgree(this,true);
        //初始化地图控件
        mapView = (MapView) findViewById(R.id.gaode_map);
        //这个地方需要捕获下异常,不然会出现编译不过的情况
        try {
    
    
            mLocationClient = new AMapLocationClient(GaodeMapActivity.this);
        }catch (Exception e) {
    
    
         Log.e(TAG, e.getMessage());
        }
        mapView.onCreate(savedInstanceState);
        if (aMap == null) {
    
    
            //展示地图
            aMap = mapView.getMap();
            Log.i(TAG,"展示地图");
        }

       @Override
       protected void onDestroy() {
    
    
        super.onDestroy();
        mapView.onDestroy();
       }

      @Override
      protected void onResume() {
    
    
        super.onResume();
        mapView.onResume();
      }

      @Override
      protected void onPause() {
    
    
        super.onPause();
        mapView.onPause();
      }

      @Override
      public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
    
    
        super.onSaveInstanceState(outState, outPersistentState);
        //在activity保存时,同时也保存地图
        mapView.onSaveInstanceState(outState);
      }

insert image description here
The effect is shown in the figure above, which completes the display of the first step map

2. Locate the blue dot

Refer to the official document.
The complete GaodeActivity code is as follows because it is a demo, so the code is written in a rough way. Please bear with me.

 private static final String TAG = "GaodeMapActivity";
    private MapView mapView;
    private AMap aMap = null;
    private double lat;
    private double lon;
    public AMapLocationClient mLocationClient = null;
    public AMapLocationClientOption mLocationOption = null;
    private Button btn_search;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gaode_map);
        btn_search = findViewById(R.id.btn_search);
        //这地方就是下面要讲的搜索导航功能
        btn_search.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View view) {
    
    
                Intent intent = new Intent(GaodeMapActivity.this, SearchActivity.class);
                startActivity(intent);
            }
        });
        MapsInitializer.updatePrivacyShow(this,true,true);
        MapsInitializer.updatePrivacyAgree(this,true);
        //初始化地图控件
        mapView = (MapView) findViewById(R.id.gaode_map);
        try {
    
    
            mLocationClient = new AMapLocationClient(GaodeMapActivity.this);
        }catch (Exception e) {
    
    
            Log.e(TAG, e.getMessage());
        }
        //设置定位回调监听
        mLocationClient.setLocationListener(mLocationListener);
        mapView.onCreate(savedInstanceState);
        if (aMap == null) {
    
    
            //展示地图
            aMap = mapView.getMap();
            Log.i(TAG,"展示地图");
        }
        MyLocationStyle myLocationStyle;
        myLocationStyle = new MyLocationStyle();
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE); //持续定位
        //设置连续定位模式下定位间隔
        myLocationStyle.interval(2000);
        myLocationStyle.strokeWidth(20f);
        aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
//aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);
        myLocationStyle.showMyLocation(true);
    }

    public AMapLocationListener mLocationListener = new AMapLocationListener() {
    
    
        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
    
    
            if (amapLocation != null) {
    
    
                if (amapLocation.getErrorCode() == 0) {
    
    
                    //定位成功回调信息,设置相关消息
                    amapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
                    amapLocation.getLatitude();//获取纬度
                    amapLocation.getLongitude();//获取经度
                    amapLocation.getAccuracy();//获取精度信息
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date date = new Date(amapLocation.getTime());
                    df.format(date);//定位时间
                    amapLocation.getAddress();//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
                    amapLocation.getCountry();//国家信息
                    amapLocation.getProvince();//省信息
                    amapLocation.getCity();//城市信息
                    amapLocation.getDistrict();//城区信息
                    amapLocation.getStreet();//街道信息
                    amapLocation.getStreetNum();//街道门牌号信息
                    amapLocation.getCityCode();//城市编码
                    amapLocation.getAdCode();//地区编码
                    amapLocation.getAoiName();//获取当前定位点的AOI信息
                    lat = amapLocation.getLatitude();
                    lon = amapLocation.getLongitude();
                    Log.v("pcw","lat : "+lat+" lon : "+lon);

                    // 设置当前地图显示为当前位置
                    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), 15));
                    MarkerOptions markerOptions = new MarkerOptions();
                    markerOptions.position(new LatLng(lat, lon));
                    markerOptions.title("当前位置");
                    markerOptions.visible(true);
                    BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background));
                    markerOptions.icon(bitmapDescriptor);
                    aMap.addMarker(markerOptions);

                } else {
    
    
                    //显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
                    Toast.makeText(GaodeMapActivity.this,
                            amapLocation.getErrorCode() + ", errInfo:"
                                    + amapLocation.getErrorInfo(), Toast.LENGTH_SHORT).show();
                }
            }
        }
    };


    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    protected void onResume() {
    
    
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
    
    
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
    
    
        super.onSaveInstanceState(outState, outPersistentState);
        //在activity保存时,同时也保存地图
        mapView.onSaveInstanceState(outState);
    }

The effect after implementation is as follows
insert image description here

3. Realize the search function

1. First we need to create a search Activity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.SearchActivity"
    android:orientation="vertical">

    <EditText
        android:id="@+id/search_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/search_rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/search_edit"
        app:layout_constraintVertical_bias="1.0"
        tools:layout_editor_absoluteX="-51dp"
        />
</LinearLayout>

The layout of the search item is as follows

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="18dp"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="城市"
        android:textSize="18sp"
        android:id="@+id/search_adapter_text"/>

</LinearLayout>

3. There must be an Adapter to display data to Recyclerview

public class RvAdapter extends RecyclerView.Adapter<RvAdapter.ViewHolder> implements View.OnClickListener {
    
    
    private final ArrayList<Tip> list;
    private final Context context;
    private final  RecyclerView rv;
    private OnItemClickListener  mOnItemClickListener;

    public RvAdapter(ArrayList<Tip> list, Context context, RecyclerView rv) {
    
    
        this.list = list;
        this.context = context;
        this.rv = rv;
    }

    @Override
    public void onClick(View view) {
    
    
        int position = rv.getChildAdapterPosition(view);

        //程序执行到此,会去执行具体实现的onItemClick()方法
        if (mOnItemClickListener != null) {
    
    
           mOnItemClickListener.onItemClick(rv, view, position, list.get(position));
            Log.i("TAG", "onClick: "+position);
        }
    }

    public interface  OnItemClickListener{
    
    
        void onItemClick(RecyclerView recyclerView,View view, int position,Tip data);
    }
    public void setmOnItemClickListener(OnItemClickListener  clickListener) {
    
    
        this.mOnItemClickListener = clickListener;
    }

    public void setData(List<Tip> list) {
    
    
        if (list != null) {
    
    
            this.list.clear();
            this.list.addAll(list);
            notifyDataSetChanged();
            Log.i("TAG", "setData: "+ list);
        }
    }

    @Override
    public RvAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        //View view = LayoutInflater.from(context).inflate(R.layout.search_item, parent ,false);
        View view = View.inflate(context, R.layout.search_item, null);
        view.setOnClickListener(this);
        return new ViewHolder(view);
    }


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    
    
        Tip tip = list.get(position);
        holder.textView.setText(tip.getName());
        Log.i("TAG", "onBindViewHolder:  getName= "+tip.getName());
    }

    @Override
    public int getItemCount() {
    
    
        return list.size();
    }
     static class ViewHolder extends RecyclerView.ViewHolder{
    
    
       private TextView textView;
        public ViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            textView = itemView.findViewById(R.id.search_adapter_text);
        }
    }

4. The following is the code of SearchActivty

public class SearchActivity extends AppCompatActivity implements Inputtips.InputtipsListener, TextWatcher,RvAdapter.OnItemClickListener {
    
    
   private RvAdapter rvAdapter;
   private Inputtips inputtips;
   private AMapNavi aMapNavi;
   private EditText editText;
   private RecyclerView recyclerView;
   private ArrayList<Tip> list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        editText = findViewById(R.id.search_edit);
        editText.addTextChangedListener(this);
        recyclerView = (RecyclerView) findViewById(R.id.search_rv);
        LinearLayoutManager layoutManager = new LinearLayoutManager(SearchActivity.this, RecyclerView.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        rvAdapter = new RvAdapter(list,SearchActivity.this,recyclerView);
        rvAdapter.setmOnItemClickListener(this);
        recyclerView.setAdapter(rvAdapter);
        inputtips = new Inputtips(this,(InputtipsQuery) null);
        inputtips.setInputtipsListener(this);
    }



    @Override
    public void onGetInputtips(List<Tip> list, int i) {
    
    
        Log.i("Tag","onGetInputtips data = "+list);
        rvAdapter.setData(list);
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    
     InputtipsQuery inputtipsQuery = new InputtipsQuery(String.valueOf(charSequence),null);
     inputtipsQuery.setCityLimit(true);
     inputtips.setQuery(inputtipsQuery);
     inputtips.requestInputtipsAsyn();
    }

    @Override
    public void afterTextChanged(Editable editable) {
    
    

    }
    @Override
    public void onItemClick(RecyclerView parent, View view, int postion, Tip data) {
    
    
      
    }

This completes the search function, the effect is as shown below

insert image description here

4. Navigation function

Official document reference
1. We need to start it through AmapNaviPage, which is a singleton mode

        //导航参数对象(起点,途径,终点,导航方式)DRIVER是导航方式(驾驶,步行...当前为驾驶)ROUTE会计算路程选择
        AmapNaviParams params = new AmapNaviParams(null, null, poi, AmapNaviType.DRIVER, AmapPageType.ROUTE);
        //传递上下文和导航参数
        AmapNaviPage.getInstance().showRouteActivity(getApplicationContext(), params, null);

2. Declaring and locating the service component needs to declare the locating service component in AndroidManifest.xml. Please declare the service component in the application tag and add the following code:

<service android:name="com.amap.api.location.APSService"/>

3. Also declare the Activity of the navigation component in AndroidMainfest

<activity
            android:name="com.amap.api.navi.AmapRouteActivity"
            android:theme="@android:style/Theme.NoTitleBar"
            android:configChanges="orientation|keyboardHidden|screenSize|navigation" />

Then attach the complete SearchActivity code

public class SearchActivity extends AppCompatActivity implements Inputtips.InputtipsListener, TextWatcher,RvAdapter.OnItemClickListener {
    
    
   private RvAdapter rvAdapter;
   private Inputtips inputtips;
   private AMapNavi aMapNavi;
   private EditText editText;
   private RecyclerView recyclerView;
   private ArrayList<Tip> list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        editText = findViewById(R.id.search_edit);
        editText.addTextChangedListener(this);
        recyclerView = (RecyclerView) findViewById(R.id.search_rv);
        LinearLayoutManager layoutManager = new LinearLayoutManager(SearchActivity.this, RecyclerView.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        rvAdapter = new RvAdapter(list,SearchActivity.this,recyclerView);
        rvAdapter.setmOnItemClickListener(this);
        recyclerView.setAdapter(rvAdapter);
        inputtips = new Inputtips(this,(InputtipsQuery) null);
        inputtips.setInputtipsListener(this);
        //这是隐私合规接口,如果不加,可能出现地图加载不出来的问题
        NaviSetting.updatePrivacyShow(this, true, true);
        NaviSetting.updatePrivacyAgree(this, true);
        try {
    
    
             //这个地方也许捕获一下异常,不然编译不过去
            aMapNavi = AMapNavi.getInstance(this);
        }catch (Exception e){
    
    
            Log.e("TAG", e.getMessage());
        }
         if (aMapNavi!=null) {
    
    
             //设置内置语音播报
             aMapNavi.setUseInnerVoice(true, false);
         }
    }



    @Override
    public void onGetInputtips(List<Tip> list, int i) {
    
    
        Log.i("Tag","onGetInputtips data = "+list);
        rvAdapter.setData(list);
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
    
     InputtipsQuery inputtipsQuery = new InputtipsQuery(String.valueOf(charSequence),null);
     inputtipsQuery.setCityLimit(true);
     inputtips.setQuery(inputtipsQuery);
     inputtips.requestInputtipsAsyn();
    }

    @Override
    public void afterTextChanged(Editable editable) {
    
    

    }
    @Override
    public void onItemClick(RecyclerView parent, View view, int postion, Tip data) {
    
    
        Log.i("TAG", "onItemClick:  点击了"+postion+"条");
        //得到点击的坐标
        LatLonPoint point = data.getPoint();
        Log.i("Tag", "坐标为"+point);
        //得到经纬度
        Poi poi = new Poi(data.getName(), new LatLng(point.getLatitude(), point.getLongitude()), data.getPoiID());
        //导航参数对象(起点,途径,终点,导航方式)DRIVER是导航方式(驾驶,步行...当前为驾驶)ROUTE会计算路程选择
        AmapNaviParams params = new AmapNaviParams(null, null, poi, AmapNaviType.DRIVER, AmapPageType.ROUTE);
        //传递上下文和导航参数
        AmapNaviPage.getInstance().showRouteActivity(getApplicationContext(), params, null);
    }
}

The implementation effect diagram is attached below. In
insert image description here
this place, you need to add such a piece of code in the applcation of AndroidMainfest, otherwise you will click to start the navigation and there will be a crash. For details, please refer to why the following code should be added

android:allowNativeHeapPointerTagging="false"

This is all the above content. If there is any preliminary preparation work, please refer to my previous article: Integrating Gaode Map SDK in Android to realize map positioning and navigation functions (1)

Guess you like

Origin blog.csdn.net/Qinbenjiaren/article/details/130743437