发布于2021-10-24 11:53 阅读(1018) 评论(0) 点赞(3) 收藏(5)
最近在研究c++与JavaScript的交互,有朋友问我安卓怎样与JavaScript交互,今天找到一个之前写的小demo,实现的是安卓webview里面的JavaScript和原生安卓进行交互。实现了安卓与JavaScript交互,就可以用html+js+css在webview实现主要界面,Java只负责一些js不好实现的功能比如文件操作,数据库操作,摄像头操作等硬件操作。
首先要在工程的AndroidManifest.xml文件申请所需权限,比如摄像头,gps定位,访问存储卡等,代码大体如下。
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.jspp.sdxjwkq.js">
- <!--完全的网络权限-->
- <uses-permission android:name="android.permission.INTERNET"/>
- <!-- 在SDCard中创建与删除文件权限 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <!-- 往SDCard写入数据权限 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <!--震动权限-->
- <uses-permission android:name="android.permission.VIBRATE"/>
- <!--摄像头权限-->
- <uses-permission android:name="android.permission.CAMERA"/>
- <uses-feature android:name="android.hardware.camera" /> <!-- 使用照相机权限 -->
- <uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 自动聚焦权限 -->
- <!--闪光灯权限-->
- <uses-permission android:name="android.permission.FLASHLIGHT"/>
- <!--获取粗略位置权限(wifi)-->
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <!--GPS权限(获取精确位置)-->
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <!--读取短信权限-->
- <uses-permission android:name="android.permission.READ_SMS"/>
- <!--发短息权限-->
- <uses-permission android:name="android.permission.SEND_SMS"/>
- <!--录制音频权限-->
- <uses-permission android:name="android.permission.RECORD_AUDIO"/>
- <application
- android:name=".BaseApplication"
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
- </manifest>
然后就是写一些方法供JavaScript调用,下面举几个例子
- package com.jspp.sdxjwkq.js;
-
- import android.app.Service;
- import android.content.Context;
- import android.content.pm.PackageManager;
- import android.hardware.Camera;
- import android.location.Location;
- import android.location.LocationManager;
- import android.os.Vibrator;
- import android.support.v4.content.ContextCompat;
- import android.webkit.JavascriptInterface;
- import android.widget.Toast;
-
- import java.util.List;
-
- /**
- * 小工具
- */
- public class Utils {
- private Camera camera;//照相机句柄
- /**
- * 震动
- * @param time 震动时长(毫秒)
- * @return
- */
- @JavascriptInterface
- public boolean vibrate(int time){
- Vibrator vibrator=(Vibrator) BaseApplication.getContext().getSystemService(Service.VIBRATOR_SERVICE);
- vibrator.vibrate(new long[]{0,time},-1);
- return true;
- }
-
- /**
- * 打开闪光灯
- * @return
- */
- @JavascriptInterface
- public boolean openFlashlight(){
- try{
- camera= Camera.open();
- if(camera!=null){
- camera.startPreview();
- Camera.Parameters parameters=camera.getParameters();
- parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
- camera.setParameters(parameters);
- return true;
- }
- return false;
- }catch (Exception e){
- return false;
- }
- }
-
- /**
- * 关闭闪光灯
- * @return
- */
- @JavascriptInterface
- public boolean closeFlashlight(){
- if(camera!=null){
- camera.getParameters().setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
- camera.setParameters(camera.getParameters());
- camera.stopPreview();
- camera.release();
- camera=null;
- return true;
- }else{
- return false;
- }
- }
-
- /**
- * 取得设备位置信息
- * @return
- */
- @JavascriptInterface
- public String getPosition(){
- LocationManager locationManager=(LocationManager) BaseApplication.getContext().getSystemService(Context.LOCATION_SERVICE);
- //获取可用的位置提供器
- String locationProvider;
- List<String> providers=locationManager.getProviders(true);
- if(providers.contains(locationManager.GPS_PROVIDER)){
- locationProvider=locationManager.GPS_PROVIDER;
- }else if(providers.contains(locationManager.NETWORK_PROVIDER)){
- locationProvider=locationManager.NETWORK_PROVIDER;
- }else{
- return "找不到地理位置获取设备";
- }
- if (ContextCompat.checkSelfPermission(BaseApplication.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
- || ContextCompat.checkSelfPermission(BaseApplication.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
- Location location=locationManager.getLastKnownLocation(locationProvider);
- if(location!=null){
- return "{longitude:"+location.getLongitude()+",latitude"+location.getLatitude()+"}";
- }else{
- return "获取地理位置失败";
- }
- }else {
- return "没有权限获取该设备地理位置";
- }
- }
- @JavascriptInterface
- public void toast(String msg){
- Toast.makeText(BaseApplication.getContext(),msg,Toast.LENGTH_LONG).show();
- }
- }
- package com.jspp.sdxjwkq.js;
- import android.webkit.JavascriptInterface;
-
- import org.json.JSONArray;
- import org.json.JSONObject;
-
- import java.io.File;
-
- /**
- * 文件操作
- */
- public class FileSystem {
- public String DirRoot="/mnt/sdcard";//文件系统的根
-
- /**
- * 创建文件夹
- * @param url(文件夹路径)
- * @return
- */
- @JavascriptInterface
- public boolean createDirByUrl(String url){
- File file=new File(this.DirRoot+url);
- if(!file.exists()){
- file.mkdirs();
- return true;
- }else{
- return false;
- }
- }
-
- /**
- * 文件是否存在
- * @param url
- * @return
- */
- @JavascriptInterface
- public boolean fileExists(String url){
- File file=new File(this.DirRoot+url);
- return file.exists();
- }
-
- /**
- * 返回文件列表
- * @param url
- * @return
- */
- @JavascriptInterface
- public String getFileListByUrl(String url){
- try{
- JSONArray jsonArray=new JSONArray();
- File file=new File(this.DirRoot+url);
- File[] subFile=file.listFiles();
- for(int i=0;i<subFile.length;i++){
- JSONObject jsonObject=new JSONObject();
- jsonObject.put("name",subFile[i].getName());//文件名
- jsonObject.put("path",subFile[i].getPath());//文件路径
- if(subFile[i].isDirectory()){//文件类型
- jsonObject.put("type","dir");
- }else{
- jsonObject.put("type","file");
- }
- jsonObject.put("size",subFile[i].length());
- jsonArray.put(i,jsonObject);
- }
- return jsonArray.toString();
- }catch (Exception e){return "error";}
- }
- }
可以看到每一个类前面都要引入android.webkit.JavascriptInterface这个包,还有就是方法都要是public的,前面标注上@JavascriptInterface,声明为JavaScript接口。
最后就是在相应的webview控件里面暴露这些接口啦,例如下面代码
- package com.jspp.sdxjwkq.js;
-
- import android.content.Context;
- import android.net.Uri;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.view.KeyEvent;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.webkit.WebView;
- import android.webkit.WebViewClient;
-
- /**
- * 软件列表
- */
- public class AppFragment extends Fragment {
- private static WebView webView;
- /**
- * 在这里写页面逻辑
- * @param savedInstanceState
- */
- @Override
- public void onActivityCreated(Bundle savedInstanceState){
- super.onActivityCreated(savedInstanceState);
- webView=getView().findViewById(R.id.webView1);
- //新窗口使用webview
- webView.setWebViewClient(new WebViewClient(){
- @Override
- public boolean shouldOverrideUrlLoading(WebView view,String url){
- view.loadUrl(url);
- return true;
- }
- });
- webView.getSettings().setJavaScriptEnabled(true);//支持javascript
- //javascript接口映射
- webView.addJavascriptInterface(new Utils(), "Utils");
- webView.addJavascriptInterface(new Sql(), "Sql");
- webView.loadUrl("file:///mnt/sdcard/jspp/system/appList.html");
- }
-
- /**
- * 用户按下返回键
- * @param keyCode
- * @param event
- * @return
- */
- public static boolean onKeyDown(int keyCode, KeyEvent event){
- if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
- webView.goBack();
- return false;
- }
- return true;
- }
- // TODO: Rename parameter arguments, choose names that match
- // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
- private static final String ARG_PARAM1 = "param1";
- private static final String ARG_PARAM2 = "param2";
-
- // TODO: Rename and change types of parameters
- private String mParam1;
- private String mParam2;
-
- private OnFragmentInteractionListener mListener;
-
- public AppFragment() {
- // Required empty public constructor
- }
-
- /**
- * Use this factory method to create a new instance of
- * this fragment using the provided parameters.
- *
- * @param param1 Parameter 1.
- * @param param2 Parameter 2.
- * @return A new instance of fragment AppFragment.
- */
- // TODO: Rename and change types and number of parameters
- public static AppFragment newInstance(String param1, String param2) {
- AppFragment fragment = new AppFragment();
- Bundle args = new Bundle();
- args.putString(ARG_PARAM1, param1);
- args.putString(ARG_PARAM2, param2);
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getArguments() != null) {
- mParam1 = getArguments().getString(ARG_PARAM1);
- mParam2 = getArguments().getString(ARG_PARAM2);
- }
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // Inflate the layout for this fragment
- return inflater.inflate(R.layout.fragment_app, container, false);
- }
-
- // TODO: Rename method, update argument and hook method into UI event
- public void onButtonPressed(Uri uri) {
- if (mListener != null) {
- mListener.onFragmentInteraction(uri);
- }
- }
- //用于页面间通信
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- if (context instanceof OnFragmentInteractionListener) {
- mListener = (OnFragmentInteractionListener) context;
- } else {
- // throw new RuntimeException(context.toString()
- // + " must implement OnFragmentInteractionListener");
- }
- }
-
- @Override
- public void onDetach() {
- super.onDetach();
- mListener = null;
- }
-
- /**
- * This interface must be implemented by activities that contain this
- * fragment to allow an interaction in this fragment to be communicated
- * to the activity and potentially other fragments contained in that
- * activity.
- * <p>
- * See the Android Training lesson <a href=
- * "http://developer.android.com/training/basics/fragments/communicating.html"
- * >Communicating with Other Fragments</a> for more information.
- */
- public interface OnFragmentInteractionListener {
- // TODO: Update argument type and name
- void onFragmentInteraction(Uri uri);
- }
- }
//javascript接口映射
webView.addJavascriptInterface(new Utils(), "Utils");
webView.addJavascriptInterface(new Sql(), "Sql");
webView.loadUrl("file:///mnt/sdcard/jspp/system/appList.html");
这几句就是添加了JavaScript接口映射,直接把实例化对象映射出去,
然后就是在js文件里使用了,比如想要手机振动一秒就可以在js里面直接写Utils.vibrate(1000);
针对js传参比较灵活的情况,java实现的时候可以对方法进行重载。
下面就是之前测试的效果
界面是用的原生的FragmentPager控件,中间白色部分是webview载入的本地网页。
可以看到在AndroidManifest.xml文件申请的那些权限,
因为应用本身没有多少图片等资源,所以打包之后也非常小巧。
原文链接:https://blog.csdn.net/sdxjwkq01/article/details/120917924
作者:程序员的人生
链接:http://www.qianduanheidong.com/blog/article/210636/7a39ce91edfb9fc1cdaa/
来源:前端黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 前端黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-3
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!