Android 使用腾讯地图定位地点
Android 利用和风天气API显示实时天气 - 拾一贰叁 - 博客园 (cnblogs.com)
之前使用和风天气的SDK在Android App上显示了实时天气情况,但是显示的地点信息是提前设置好的
因此需要借助腾讯地图的SDK实现手动设定地点,如图:
在一个Activity的Fragment中点击"获取位置"
打开地图,跳转到如图所示的Activity,可以选择地点,然后点击确定(这个Activity本质上是一个WebView加一个Button,也就是下文的MappingActivity)
可以看出原来的Activity/Fragment得到了选定的地理位置,并将控件Button的Text文字修改成了这个地理位置。
使用腾讯位置服务的SDK还可以获得选择地点的其他信息,如经纬度之类的,在和风天气中通过经纬度显示当地天气。
关于如何获取腾讯位置服务可以参考官方文档,也可以参考之前和风天气的服务获取过程,基本上都差不多
Android定位SDK | 腾讯位置服务 (qq.com)
Key名称:随便取一个
描述:随便填一下
地图SDK:下边填的那个是应用程序的包名,com.xxx.xxx的那种
WebServiceAPI:不知道这个有啥用,之前死活加载不出来,一直显示获取消息列表失败,把这个选项勾选上后诡异地成功了,于是一直勾选着它了
接下来是对自己的工程文件操作了
在AndroidManifest.xml里配置刚刚在平台上获取的Key(就是那一长串字符)
<application>
...
<meta-data android:name="TencentMapSDK" android:value="您申请的Key" />
</application>
然后给予一堆权限
<!-- 通过GPS得到精确位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 通过网络得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 访问网络,某些位置信息需要从网络服务器获取 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 访问WiFi状态,需要WiFi信息用于网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 修改WiFi状态,发起WiFi扫描, 需要WiFi信息用于网络定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 访问网络状态, 检测网络的可用性,需要网络运营商相关信息用于网络定位 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 访问网络的变化, 需要某些信息用于网络定位 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!-- 蓝牙扫描权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 前台service权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- 后台定位权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<!-- A-GPS辅助定位权限,方便GPS快速准确定位 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
在build.gradle(Module:app)里添加依赖
implementation 'com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.4.9'
(官方文档里写了多种方法,比较简单的做法就是直接在build.gradle里添上这一行就行了)
创建一个MappingActivity
布局文件为
activity_mapping.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MappingActivity">
<WebView
android:id="@+id/web_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="56dp"
app:layout_constraintBottom_toTopOf="@+id/btn_map"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</WebView>
<Button
android:id="@+id/btn_map"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:background="@drawable/loginbuttonbackground"
android:gravity="center"
android:text="确定"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="16dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果
MappingActivity的java代码为:
package com.xxx.xxx;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.DecimalFormat;
public class MappingActivity extends Activity {
private WebView mWebView;
private Button btn_map;
private String positionname;//位置名
private String rcity="";//城市
private String address="未获取到位置";//详细地址
private String latng="";//经纬度,纬度在前
private String lat="";//纬度
private String lng="";//经度
private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mapping);
mWebView=findViewById(R.id.web_map);
btn_map=findViewById(R.id.btn_map);
String mUrl = "https://apis.map.qq.com/tools/locpicker?search=1&type=0&backurl=http://callback&key=【Key值】&referer=【应用名】";
WebSettings settings = mWebView.getSettings();
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);
settings.setSupportMultipleWindows(true);
settings.setJavaScriptEnabled(true);
settings.setSavePassword(false);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setMinimumFontSize(settings.getMinimumFontSize() + 8);
settings.setAllowFileAccess(false);
settings.setTextSize(WebSettings.TextSize.NORMAL);
mWebView.setVerticalScrollbarOverlay(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.startsWith("http://callback")) {
view.loadUrl(url);
} else {
try {
//转utf-8编码
String decode = URLDecoder.decode(url, "UTF-8");
// LogUtil.i(decode);
//转uri,然后根据key取值
uri = Uri.parse(decode);
Log.e("address",uri.toString());
latng = uri.getQueryParameter("latng");//纬度在前,经度在后,以逗号分隔
String[] split = latng.split(",");
DecimalFormat decimalFormat=new DecimalFormat(".00");
lat=decimalFormat.format(Float.parseFloat(split[0]));//纬度
lng=decimalFormat.format(Float.parseFloat(split[1]));//经度
rcity = uri.getQueryParameter("city");//城市
address = uri.getQueryParameter("addr");//地理位置
positionname=uri.getQueryParameter("name");//地址名
//name是地址名,addr是详细地址,city是城市,latng是经纬度(不过纬度在前边)
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return true;
}
});
mWebView.loadUrl(mUrl);
/**最下边那个button的作用是点击后直接返回上一个activity
与此同时将选定的位置数据传递给那个Activity
*/
btn_map.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MappingActivity.this,address.toString()+latng.toString(),Toast.LENGTH_LONG).show();
System.out.println("信息:"+uri.toString());
Intent intent = getIntent();
intent.putExtra("name", positionname);
intent.putExtra("city", rcity);
intent.putExtra("address", address);
intent.putExtra("lat", lat);
intent.putExtra("lng", lng);
MappingActivity.this.setResult(0,intent);//resultCode被设为0了,这个视实际情况而定,涉及到通过Intent在Activity间传递数据的知识
MappingActivity.this.finish();
}
});
}
}
在之前的和风天气中有这样一个接口
QWeather.getWeatherNow(Context context, String location, Lang lang, Unit unit,QWeather.OnResultWeatherNowListener listener) ;
在这个接口里String location决定了查询天气的地点信息,这个变量可以是城市代码,比如“CN101180101”(郑州的城市代码),
也可以是经纬度,例如“113.66245,34.78181”(郑州的经纬度)(注意这个是经度在前,纬度在后)
将刚才从腾讯地图中获取的经纬度传递进去,就可以实现不同的地点显示不同的天气情况了。
补充:Fragment里接收来自MappingActivity信息的代码
//一个Fragment向另外一个Activity(MappingActivity)跳转,写在OnCreateView()里
btn_presetting_getposition.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent intent=new Intent(getActivity(),MappingActivity.class);
startActivityForResult(intent,0);//请求码设为0
}
});
//-----写在OnCreateView外边
//该方法以回调方式来获取指定Activity返回的结果
@Override
public void onActivityResult(int requestCode,int resultCode,Intent intent){
//核实请求码和答复码
if(requestCode==0&&resultCode==0){
//Toast.makeText(getActivity(),"回传成功",Toast.LENGTH_LONG).show();
try{
Bundle bundle=intent.getExtras();
//iv_portrait.setImageResource(bundle.getInt("imageid"));
btn_presetting_getposition.setText(bundle.getString("address"));
position=bundle.getString("name");
city=bundle.getString("city");
address=bundle.getString("address");
lat=bundle.getString("lat");
lng=bundle.getString("lng");
}catch(java.lang.RuntimeException e){
Toast.makeText(getActivity(),"获取信息失败",Toast.LENGTH_SHORT).show();
}
}
}