20212408 2023-2024-2《移动平台开发与实践》第5次作业

20212408 2023-2024-2《移动平台开发与实践》第5次作业

一、实验内容

设计并开发一个地图应用系统。
该实验需提前申请百度API Key,调用接口实现百度地图的定位功能、地图添加覆盖物和显示文本信息。

二、实验过程

(一)实验准备

  • 百度地图KPI申请
    搜索百度地图控制台,直接申请百度地图KPI。学生认证上传学信网的截图即可。但是学生认证审核时间可能会比较长,这时可以选择使用个人认证,这样直接就可以完成认证,不需要等待审核,速度比较快。
    跟着百度教程创建ak AK创建教程
    请添加图片描述
    请添加图片描述
    创建好后,下载所需要的sdk包,导入到项目中,放在libs目录下。包括下载下来的jar包和那些文件夹内容都放进去。
    在这里插入图片描述
    然后在app目录下的build.gradle文件中android块中配置sourceSets标签,这里需要注意,百度官方给出的教程中的代码并不适用于新版的Android studio,所以将其输入时会发生报错,这里需要我们自己修改成新版的代码,具体如下:
 sourceSets {
        getByName("main") {
            jniLibs.srcDirs("libs")
        }
    }

然后往工程中添加jar文件,这后面跟着教程走就不会有什么问题,可以一遍通。
在这里插入图片描述

(二)实验步骤

在AndroidManifest.xml申请对应权限

<!--百度定位所需要权限,前面是LOCATE权限组的2个危险权限-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!--百度定位所需要的普通权限-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <!--因为程序要与百度云服务交互-->
    <uses-permission android:name="android.permission.INTERNET"/>

在AndroidManifest.xml中的中添加下面的代码,将自己的AK码填入其中
在这里插入图片描述在这里插入图片描述

注意!!这个上面com.baidu.lbsapi虽然下面有波浪号,感觉是有问题,但是千万千万不要自动修改,否则后面会有报错,很难察觉到是这里的问题。

然后需要再mainactivity中添加代码,我使用的就是老师指导书中给出的代码,大部分代码都是正确可以使用,只有一些小的问题,可能需要根据自己的电脑进行调整。

package com.example.baidumap

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.baidu.location.BDLocation
import com.baidu.location.BDLocationListener
import com.baidu.location.LocationClient
import com.baidu.location.LocationClientOption
import com.baidu.mapapi.SDKInitializer
import com.baidu.mapapi.common.BaiduMapSDKException
import com.baidu.mapapi.map.BaiduMap
import com.baidu.mapapi.map.BitmapDescriptorFactory
import com.baidu.mapapi.map.MapStatusUpdateFactory
import com.baidu.mapapi.map.MapView
import com.baidu.mapapi.map.MarkerOptions
import com.baidu.mapapi.model.LatLng


/*
   百度地图应用,包含定位信息和地图显示
   一般需要打开定位服务,选择高精度定位模式,有网络连接
   需要在清单文件里使用百度云服务(参见清单文件service标签)
   需要创建应用(模块)的Key,并写入清单文件(参见清单文件meta标签)
*/
class MainActivity : AppCompatActivity() {
    var mLocationClient: LocationClient? = null //定位客户端
    var mapView: MapView? = null //Android Widget地图控件
    var baiduMap: BaiduMap? = null
    var isFirstLocate = true
    var tv_Lat: TextView? = null //纬度
    var tv_Lon: TextView? = null //经度
    var tv_Add: TextView? = null //地址
    protected override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //如果没有定位权限,动态请求用户允许使用该权限
        LocationClient.setAgreePrivacy(true)

        SDKInitializer.setAgreePrivacy(applicationContext, true)

        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                1
            )
        } else {
            requestLocation()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String?>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            1 -> if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "没有定位权限!", Toast.LENGTH_LONG).show()
                finish()
            } else {
                requestLocation()
            }
        }
    }

    private fun requestLocation() {
        initLocation()
        mLocationClient!!.start()
    }

    private fun initLocation() {  //初始化
        mLocationClient = LocationClient(applicationContext)
        mLocationClient!!.registerLocationListener(MyLocationListener())
        SDKInitializer.initialize(applicationContext)
        setContentView(R.layout.activity_main)
        mapView = findViewById(R.id.bmapView)
        baiduMap = mapView!!.map
        tv_Lat = findViewById(R.id.tv_Lat)
        tv_Lon = findViewById(R.id.tv_Lon)
        tv_Add = findViewById(R.id.tv_Add)
        val option = LocationClientOption()
        //设置扫描时间间隔
        option.setScanSpan(1000)
        //设置定位模式,三选一
        option.locationMode = LocationClientOption.LocationMode.Hight_Accuracy
        /*option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);*/
        //设置需要地址信息
        option.setIsNeedAddress(true)
        //保存定位参数
        mLocationClient!!.locOption = option
    }

    //内部类,百度位置监听器
    private inner class MyLocationListener : BDLocationListener {
        override fun onReceiveLocation(bdLocation: BDLocation) {
            tv_Lat!!.text = bdLocation.latitude.toString() + ""
            tv_Lon!!.text = bdLocation.longitude.toString() + ""
            tv_Add!!.text = bdLocation.addrStr
            if (bdLocation.locType == BDLocation.TypeGpsLocation || bdLocation.locType == BDLocation.TypeNetWorkLocation) {
                navigateTo(bdLocation)
            }
        }
    }

    private fun navigateTo(bdLocation: BDLocation) {
        val ll = LatLng(bdLocation.latitude, bdLocation.longitude)
        if (isFirstLocate) {

            val update = MapStatusUpdateFactory.newLatLng(ll)
            baiduMap!!.animateMapStatus(update)
            isFirstLocate = false
        }
        val markerOptions = MarkerOptions().position(ll)
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker))
        baiduMap!!.addOverlay(markerOptions)
    }

    protected override fun onResume() {
        super.onResume()
        mapView!!.onResume()
    }

    protected override fun onPause() {
        super.onPause()
        mapView = findViewById(R.id.bmapView) as MapView?
        mapView!!.onResume()
    }

    protected override fun onDestroy() {
        super.onDestroy()
        mLocationClient!!.stop()
        mapView!!.onDestroy()
    }
}

在activity_main.xml中加入下面代码:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">

    <!--百度地图控件-->
    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true" />
    <!--位置文本布局的背景色代码的前2位代码为透明度-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#e0000000"
        android:orientation="vertical" >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="20dp"
            android:orientation="horizontal" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="纬度:"
                android:textColor="#ffffff"
                android:textSize="15dp" />
            <TextView
                android:id="@+id/tv_Lat"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textColor="#ffffff"
                android:textSize="15dp" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="经度:"
                android:textColor="#ffffff"
                android:textSize="15dp" />
            <TextView
                android:id="@+id/tv_Lon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textColor="#ffffff"
                android:textSize="15dp" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal" >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="地址:"
                android:textColor="#ffffff"
                android:textSize="15dp" />

            <TextView
                android:id="@+id/tv_Add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:textColor="#ffffff"
                android:textSize="15dp" />
        </LinearLayout>
    </LinearLayout>

</FrameLayout>

然后进行运行调试,这个实验要求通过权限,我是选择使用真机进行测试,但是开始的时候由于我的手机在进行USB调试时选择的一直时仅充电,我的Android studio无法正确检测到手机,后面察觉到将其关闭即可。

(三)运行结果

运行代码,可以看到运行结果,大致定位是准确的,经纬度也是正确,但是没有给出我所在位置的标记。

百度地图测试

于是从网上查找资料进行学习,找到一种较为简单的给出定位标记的方法,具体代码如下:

val markerOptions = MarkerOptions().position(ll)
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.marker))
        baiduMap!!.addOverlay(markerOptions)

在navigateTo方法中,定位到用户的位置后,使用MarkerOptions方法BaiduMap.addOverlay在地图上添加一个标记。
不过前提是需要再res/drawable目录下有一个名为marker.png的图片文件作为标记进行显示。
运行效果如下:

手机测试

三、问题与解决方案

问题1:没有申请隐私权限导致应用无法运行?

解决方案:发生的原因是百度给出的一些代码都是有些过时的,不能直接进行调用,需要进行一些修改,具体修改代码如下:


LocationClient.setAgreePrivacy(true)
 
        SDKInitializer.setAgreePrivacy(applicationContext, true)
        try {
            // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
            SDKInitializer.initialize(applicationContext)
        } catch (e: BaiduMapSDKException) {
        }

这样修改后就不会提示隐私权限错误了。

问题2:项目总是提示:You need to use a Theme.AppCompat theme (or descendant) with this activity

解决方案:

根据提示来使用AppCompat的theme,即将AndroidManifest.xml文件中关于Activity的主题配置改成:

android:theme=“@style/Theme.AppCompat.Light.NoActionBar”

设置透明Activity:
在你的AndroidManifest里的Activity标签里配置透明主题:

android:theme=”@android:style/Theme.Translucent”
android:theme=”@android:style/Theme.Translucent.NoTitleBar”
android:theme=”@android:style/Theme.Translucent.NoTitleBar.Fullscreen”

第一种保留标题和状态栏,其他为透明色
第二种保留状态栏,其他为透明色
第三种全屏透明
解决方法

四、心得体会

通过这次实验,我深入学习了百度地图API的使用方法,并成功实现了地图定位和显示功能。在开发过程中,遇到了很多挑战,比如如何申请正确的隐私权限。但通过查阅官方文档、搜索相关资料和不断的尝试,最终完成了实验任务。
在实验中,官方文档提供了很大的帮助,使我能够逐步掌握API的使用技巧。通过不断尝试和调整代码,解决了在实现过程中遇到的各种问题。这次实验让我认识到了,在开发中时刻关注API的最新变化是非常的。只有这样,才能在遇到问题时及时找到解决方案,确保重要的开发任务顺利完成。
总的来说,这次实验不仅让我掌握了百度地图API的基本使用方法,还提升了我解决实际开发问题的能力。这些经验和教训对于今后的开发工作非常有价值。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值