一、H5链接打开App
点击浏览器中的URL,如何启动App呢?
1、HTML链接处理
首先做成HTML的内容,url格式如下:
<a href="[scheme]://[host]/[path]?[query]">启动应用程序</a>
说明
:
schema: 判断启动的App
host: 标记
path: 标记,可无
query: 传值的(key,value)键值对,可无
例如:
<a href="myapp://jp.app/openwith?name=zhangsan&age=26">启动应用程序</a>
本例中做如下超链接跳转:
<a href="finance://pay.com/mpos?orderId=1020160126"> Open APP </a>
其中:
schema ---- finance 对应android中 android:schema
全部Html源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>mpos</title>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0">
<meta name="imagemode" content="force">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
</head>
<body>
<h1>H5打开APP</h1>
<a href="finance://pay.com/mpos?orderId=102016000"> Open APP </a>
</body>
</html>
2、android中如何处理?
1)在AndroidManifest.xml文件中,在需要跳转到的Activity中添加如下声明:
<activity
android:name=".ui.activity.OrderDetailActivity"
android:configChanges="keyboardHidden|orientation"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/CustomTitle">
<intent-filter>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data
android:host="pay.com"
android:pathPrefix="/mpos"
android:scheme="finance" />
</intent-filter>
</activity>
2)如何获取链接中传递的数据?
if (getIntent() != null) {
if (Intent.ACTION_VIEW.equals(action)) {
Uri uri = Uri.parse(getIntent().getDataString());
if (uri != null) {
String orderId = uri.getQueryParameter("orderId");
}
}
}
3
、应该注意的地方?
1)链接打开的Activity中,【android.intent.action.MAIN】和【android.intent.category.LAUNCHER】这2个,不能与这次追加的内容混合在一起;如果跳转的刚好是启动Activity,可以写一个类继承启动类。
2)参考:
二、App打开H5
使用WebView加载,传值可参考框架JsBridgeWebView。
GitHub地址:https://github.com/lzyzsd/JsBridge
加载远程html:webView.loadUrl("http://www.baidu.com");
加载本地html:webView.loadUrl("file:///android_asset/web_app.html");
三、App打开App
例如,点击app1某个页面中的按钮,要打开app2,
1、先检测是否安装了app2,客人通过包名检测;
2、安装,例如打开微信,如果没有安装就跳转到下载页:
try {
PackageManager packageManager = getPackageManager();
Intent intent=new Intent();
intent = packageManager.getLaunchIntentForPackage("com.tencent.mm");
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Intent viewIntent = new
Intent("android.intent.action.VIEW",Uri.parse("http://weixin.qq.com/"));
startActivity(viewIntent);
}
或者
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(app2PackageName, className);
intent.setComponent(cn);
startActivity(intent);
3、如何从.aar中的某个页面跳转到主项目的某个页面?
使用隐式Intent跳转,具体如下:
1)主项目中:
<activity
android:name="com.ddqb.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="com.ddqb.MainActivity"/>
<category android:name="android.intent.category.DEFAULT" /> <!--要设置一下category-->
</intent-filter>
</activity>
findViewById(R.id.enter_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(LoginTestAcitvity.this, TestActivity.class); // TestActivity为.aar依赖库中的页面
startActivity(intent);
}
});
2).aar项目中:
findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.ddqb.MainActivity");
intent.addCategory("android.intent.category.DEFAULT");
TestActivity.this.startActivity(intent);
}
});
四、H5与App交互
1、WebView基础设置如下:
String mUrl = "http://10.0.41.19:8099/TomcatTest/web_app_upload_image.html";
WebSettings webSettings = webView.getSettings();
//设置WebView属性,能够执行Javascript脚本
webSettings.setJavaScriptEnabled(true);
//设置可以访问文件
webSettings.setAllowFileAccess(true);
//设置支持缩放
webSettings.setBuiltInZoomControls(true);
//加载需要显示的网页
// 加载 asset目录下的本地html文件: mUrl = "file:///android_asset/web_app.html"
webView.loadUrl(mUrl);
//设置WebViewClient用来辅助WebView处理各种通知请求事件等,如更新历史记录、网页开始加载/完毕、报告错误信息等
webView.setWebViewClient(new WebViewClient() {
// 以下方法避免 自动打开系统自带的浏览器,而是让新打开的网页在当前的WebView中显示
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
// 用于辅助WebView处理JavaScript的对话框、网站图标、网站标题以及网页加载进度等
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onReceivedTitle(WebView view, String title) {
tv_title.setText(title);
}
});
// 使 H5可调用Native方法: android.nativeMethod()
webView.addJavascriptInterface(new MyJsInterface(), "android");
2、H5 调用 Native 方法实现 H5页面 按钮点击事件处理,代码如下:
<input type="button" value="JS Call Native: Toast Message" οnclick="android.toastMessage()">
App WebViewActivity类中处理:
public class MyJsInterface {
@JavascriptInterface
public void toastMessage(String msg) {
Toast.makeText(WebViewActivity.this, "app to H5 toast " + msg, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(WebViewActivity.this, FirstActivity.class);
WebViewActivity.this.startActivity(intent);
}
3、Native 传递数据给 H5,场景:点击原生页面的标题栏按钮,给H5页面传值 并且更新 H5页面:
// 点击原生按钮,向H5页面发送数据,可更新H5页面
tv_click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String msg = "from Native";
// loadUrl必须在主线程中执行
webView.loadUrl("javascript:toNative('" + msg + "')");
}
});
H5 中页面数据更新代码:
<input type="text" value="hhhh" id="pp"/>
<script type="text/javascript">
// 2. js供 Native 调用的方法
function toNative(msg) {
alert("Hello, from H5, received msg: " + msg);
var p = document.getElementById("pp");
p.value = msg;
}
</script>
五、H5页面从App图库中选择图片并在H5页面显示所选图片:
步骤一:重写onShowFileChooser / openFileChooser 方法(还要兼容其他各个版本)
private static final int REQUEST_LOAD_IMAGE_FROM_GALLERY = 0x10;
private ValueCallback<Uri> mSingleFileCallback;
private ValueCallback<Uri[]> mMultiFileCallback;
private Uri imageUri;
private void setWebChromeClient() {
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onReceivedTitle(WebView view, String title) {
tv_title.setText(title);
}
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
Log.e("Webview", "onShowFileChooser");
mMultiFileCallback = filePathCallback;
openGallery();
return true; // 一定要return true 防止下次回到 WebView页面重新调用,抛异常 duplicate result
}
// 5.0以下的文件上传监听方法
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
Log.e("Webview", "openFileChooser");
mSingleFileCallback = uploadMsg;
openGallery();
}
});
}
private void openGallery() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_LOAD_IMAGE_FROM_GALLERY);
}
步骤二:在onActivityResult 中获取所选图片 uri,回调给 H5(目前代码有点小缺陷,图片需要压缩,因为在H5加载 base64本地图片是耗时操作,要先压缩图片);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_LOAD_IMAGE_FROM_GALLERY) {
if (mSingleFileCallback == null && mMultiFileCallback == null) {
return;
}
Uri tempUri = null;
if (data != null) {
String url = CommonUtil.getPath(WebViewActivity.this, data.getData());
File temp = new File(url);
tempUri = Uri.fromFile(temp);
}
if (mSingleFileCallback != null) { // 5.0以下处理方式
if (data != null) {
mSingleFileCallback.onReceiveValue(tempUri);
} else {
mSingleFileCallback.onReceiveValue(imageUri);
}
mSingleFileCallback = null;
} else if (mMultiFileCallback != null) { // 5.0版本以上
Uri[] uris = null;
if (data == null) {
uris = new Uri[] {imageUri};
} else {
// 多选图片[图片一定要压缩,转化为base网页加载很慢]
String dataString = data.getDataString();
ClipData clipData = data.getClipData();
if (clipData != null) {
int size = clipData.getItemCount();
uris = new Uri[size];
for (int i = 0; i < size; i++) {
// 将所选图片的 url保存到 uris数组中
uris[i] = clipData.getItemAt(i).getUri();
}
}
if (!TextUtils.isEmpty(dataString)) {
uris = new Uri[] {Uri.parse(dataString)};
}
}
if (uris == null) {
mMultiFileCallback.onReceiveValue(null);
mMultiFileCallback = null;
} else {
mMultiFileCallback.onReceiveValue(uris);
mMultiFileCallback = null;
}
}
}
}
步骤三:在html页面中,使用 FileReader 获取上传的图片base64编码并显示在img标签:
<input accept="image/*" capture="camera" id="imgFile" name="imgFile" type="file" οnchange="previewFile()" > <br/>
<p></p>
<img src="" id="img" />
function previewFile() {
var img = document.getElementById("img");
// 仅限上传单张图片
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener("load", function () {
img.src = reader.result; // 存储在本地的图片的base64编码
alert("result=" + reader.result);
}, false);
if (file) {
reader.readAsDataURL(file);
}
}