在开发一个安卓应用,需要用到路径规划的功能,但是再次吐槽百度地图的SDK,总之我是折腾半天都总是bug,遂考虑直接内嵌网页。
百度地图的网页也有相应的api,可以用但是不好用,它必须获得经纬度才能准确定位好吗,而且不具备位置搜索功能,如果自动定位失败或者定位到重名的地方了,倒是可以直接在地图上找,但是让用户自己去世界上找自己的位置真的好吗…不去找截图了,想尝试的请自便,总之难用又难改。
那么我所用的,便是正儿八经的百度地图网页版了,没错就是那个官网。
电脑版长这样,当然app和这个没关系,只是给看看:
这个网站做的还是不错的,毕竟百度大厂,响应式布局还是做了的,下面就是我们的主角:手机版网页如下,不要注意浏览器插件啊喂,请记下这个URL,这就是我们需要用到的:
https://map.baidu.com/mobile/webapp/index/index/
说起来手机版和电脑版的网页,定位方式是不同的,电脑版网页可以根据ip定位个大概,但是手机版网页大概是想通过GPS定位了,然而室内搜不到信号
这都不重要,下面说正经的
完整代码我放在最后面,这里先只放重点
首先当然是使用webView加载网站了
先说几点需要注意的:
- 如果说提示说 http和https 不能混合加载,那么加入如下代码:
int version = Build.VERSION.SDK_INT;
if(version >= 21) {
webView.getSettings().setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//允许混合加载http与https
}
webView.loadUrl("https://map.baidu.com/mobile/webapp/index/index/");
然后运行结果如下图:
进入该页面后,点击路线,然后用户自己输入起点和终点就可以开始导航了。这样似乎凑合了,但是肯定不完美啊,程序不就是用来方便用户的么,居然连自动输入都做不到吗?
答案当然是可以的,使用的方法嘛,js注入!所以这就是我研究这东西研究了两天的成果,核心只有可以缩成2行代码的三行代码喵喵喵
经过漫长的实验,的确可以通过js中注入的方式点击那个路径键然后跳转到后一个页面,但是js往里面填入值就不行了,原因猜测是页面还没加载好就执行了js代码。
我原本的js代码是,事实是只执行了前两句。
var qq = $('#fis_elm_pager__qk_4 div div div ul li:nth-child(3) a');
qq.click();
$('#se-txt-start').val(start);
$('#se-txt-end').val(end);
所以直接进入路径按键对应的链接了,之前总感觉其URL里会有BUG潜伏,但是此刻也别无他法了。
所以点击路径后的URL,我这儿如下,中间乱码是一些中文,会在第一个页面就定位了然后传到第二个页面,没发现有啥用,但是删了又不行。
https://map.baidu.com/mobile/webapp/index/index/qt=cur&wd=%E5%8C%97%E4%BA%AC%E5%B8%82&from=maponline&tn=m01&ie=utf-8=utf-8/tab=line/?fromhash=1
关于js注入的七七八八我就不在此赘述了,下面直接写核心方法吧。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
....
@Override
public void onPageFinished(WebView view, String url) {
String s = "$('#se-txt-start').val('长沙理工大学');$('#se-txt-end').val('湖南大学');";
webView.loadUrl("javascript:" + s);
super.onPageFinished(view, url);
}
}
如果js代码运行有问题的,请检查以下几句代码,如果没有就加上:
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
webView.getSettings().setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
想要可运行程序:请点击这是GITHUB链接
下载党注意本软件并不是为了写出该demo而作的,目前还不完善,下载本DEMO请看准WebNav_1 这个分支下载(上述链接默认是这个,不要下master,那个是陈年老版本了)使用方法为:不要管别的,点击最下方的导航就可以进入该页面了。
嘿嘿附上最终运行截图,点击搜索即可导航,而且如果位置不是唯一确定的话,点击搜索会让你选择的
下面放上我这一整个activity的代码吧,没有xml布局,这个布局一整个就是一个webView,还是用代码加进去的,所以按理说改一下类名后复制到其他activity中也是可以正常用的。
package com.yinyoupoet.seekbyscan;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.io.InputStream;
public class NavigatorActivity extends AppCompatActivity {
private WebView webView;
private long exitTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigator);
webView = new WebView(this);
//webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient(){
//解决显示与跳转问题
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url == null) return false;
Log.d("MY_URL", url);
try{
if(url.startsWith("baidumap://")){
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}catch (Exception e){
return false;
}
webView.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
//String s = "var qq = $('#fis_elm__4 div div div ul li:nth-child(3) a'); qq.click();$('#se-txt-start').val('长沙理工大学');$('#se-txt-end').val('湖南大学'); window.alert('js injection success');";
String s = "$('#se-txt-start').val('长沙理工大学');$('#se-txt-end').val('湖南大学');";
webView.loadUrl("javascript:" + s);
super.onPageFinished(view, url);
}
});
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
webView.getSettings().setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
webView.getSettings().setSupportZoom(true);//是否可以缩放,默认true
webView.getSettings().setBuiltInZoomControls(true);//是否显示缩放按钮,默认false
webView.getSettings().setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式
webView.getSettings().setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题
webView.getSettings().setAppCacheEnabled(true);//是否使用缓存
webView.getSettings().setDomStorageEnabled(true);//DOM Storage
int version = Build.VERSION.SDK_INT;
if(version >= 21) {
webView.getSettings().setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//允许混合加载http与https
}
// displayWebview.getSettings().setUserAgentString("User-Agent:Android");//设置用户代理,一般不用
//webView.setWebChromeClient(new WebChromeClient());
webView.loadUrl("https://map.baidu.com/mobile/webapp/index/index/qt=cur&wd=%E5%8C%97%E4%BA%AC%E5%B8%82&from=maponline&tn=m01&ie=utf-8=utf-8/tab=line/?fromhash=1");
setContentView(webView);
}
}