Integre el SDK de mapas de Gaode en Android para realizar funciones de navegación y posicionamiento de mapas (2)

Seguimos el artículo anterior y continuamos implementando el SDK integrado con el mapa de Gaode en Android para realizar las funciones de posicionamiento, búsqueda y navegación del mapa.

¿Cómo realizar el mapa en el teléfono móvil?

1. Configure la aplicación de permisos en AndroidManifest

Puede consultar el documento oficial.

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

Después de Android 6.0, debe solicitar permiso de forma dinámica. No lo explicaré en detalle aquí.

Establecer la clave del mapa Gaode

Agregue la clave anterior en la plataforma de alto desarrollador a la etiqueta de la aplicación del archivo androidMainfest, el código es el siguiente

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

Mi clave es ba63b...
inserte la descripción de la imagen aquí

Inicializar el control del mapa

Primero, cree una nueva Activiy que aloje el mapa y luego inicialice 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>

Luego inicialice el mapa vacío en la Actividad, aquí debe comprender que el ciclo de vida de la Actividad está vinculado a este mapa

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);
      }

inserte la descripción de la imagen aquí
El efecto se muestra en la figura anterior, que completa la visualización del primer mapa de pasos

2. Localiza el punto azul

Consulte el documento oficial.
El código completo de GaodeActivity es el siguiente porque es una demostración, por lo que el código está escrito de manera aproximada. Tenga paciencia conmigo.

 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);
    }

El efecto después de la implementación es el siguiente
inserte la descripción de la imagen aquí

3. Realizar la función de búsqueda

1. Primero necesitamos crear una actividad de búsqueda

<?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>

El diseño del elemento de búsqueda es el siguiente

<?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. Debe haber un adaptador para mostrar datos en 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. El siguiente es el código de 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) {
    
    
      
    }

Esto completa la función de búsqueda, el efecto es como se muestra a continuación

inserte la descripción de la imagen aquí

4. Función de navegación

Referencia del documento oficial
1. Necesitamos iniciarlo a través de AmapNaviPage, que es un modo singleton

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

2. La declaración y ubicación del componente de servicio debe declarar el componente de servicio de ubicación en AndroidManifest.xml. Declare el componente de servicio en la etiqueta de la aplicación y agregue el siguiente código:

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

3. Declare también la Actividad del componente de navegación en AndroidMainfest

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

Luego adjunte el código completo de SearchActivity

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);
    }
}

El diagrama del efecto de implementación se adjunta a continuación. En
inserte la descripción de la imagen aquí
este lugar, debe agregar dicho fragmento de código en la aplicación de AndroidMainfest, de lo contrario, hará clic para iniciar la navegación y habrá un bloqueo. Para obtener más detalles, consulte por qué el se debe agregar el siguiente código

android:allowNativeHeapPointerTagging="false"

Este es todo el contenido anterior. Si hay algún trabajo de preparación preliminar, consulte mi artículo anterior: Integración de Gaode Map SDK en Android para realizar funciones de navegación y posicionamiento de mapas (1)

Supongo que te gusta

Origin blog.csdn.net/Qinbenjiaren/article/details/130743437
Recomendado
Clasificación