本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(7)

安卓JAVA与javascript交互的实现

发布于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定位,访问存储卡等,代码大体如下。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.jspp.sdxjwkq.js">
  4. <!--完全的网络权限-->
  5. <uses-permission android:name="android.permission.INTERNET"/>
  6. <!-- 在SDCard中创建与删除文件权限 -->
  7. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
  8. <!-- 往SDCard写入数据权限 -->
  9. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  10. <!--震动权限-->
  11. <uses-permission android:name="android.permission.VIBRATE"/>
  12. <!--摄像头权限-->
  13. <uses-permission android:name="android.permission.CAMERA"/>
  14. <uses-feature android:name="android.hardware.camera" /> <!-- 使用照相机权限 -->
  15. <uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 自动聚焦权限 -->
  16. <!--闪光灯权限-->
  17. <uses-permission android:name="android.permission.FLASHLIGHT"/>
  18. <!--获取粗略位置权限(wifi)-->
  19. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  20. <!--GPS权限(获取精确位置)-->
  21. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  22. <!--读取短信权限-->
  23. <uses-permission android:name="android.permission.READ_SMS"/>
  24. <!--发短息权限-->
  25. <uses-permission android:name="android.permission.SEND_SMS"/>
  26. <!--录制音频权限-->
  27. <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  28. <application
  29. android:name=".BaseApplication"
  30. android:allowBackup="true"
  31. android:icon="@mipmap/ic_launcher"
  32. android:label="@string/app_name"
  33. android:roundIcon="@mipmap/ic_launcher_round"
  34. android:supportsRtl="true"
  35. android:theme="@style/AppTheme">
  36. <activity
  37. android:name=".MainActivity"
  38. android:label="@string/app_name">
  39. <intent-filter>
  40. <action android:name="android.intent.action.MAIN" />
  41. <category android:name="android.intent.category.LAUNCHER" />
  42. </intent-filter>
  43. </activity>
  44. </application>
  45. </manifest>

然后就是写一些方法供JavaScript调用,下面举几个例子

  1. package com.jspp.sdxjwkq.js;
  2. import android.app.Service;
  3. import android.content.Context;
  4. import android.content.pm.PackageManager;
  5. import android.hardware.Camera;
  6. import android.location.Location;
  7. import android.location.LocationManager;
  8. import android.os.Vibrator;
  9. import android.support.v4.content.ContextCompat;
  10. import android.webkit.JavascriptInterface;
  11. import android.widget.Toast;
  12. import java.util.List;
  13. /**
  14. * 小工具
  15. */
  16. public class Utils {
  17. private Camera camera;//照相机句柄
  18. /**
  19. * 震动
  20. * @param time 震动时长(毫秒)
  21. * @return
  22. */
  23. @JavascriptInterface
  24. public boolean vibrate(int time){
  25. Vibrator vibrator=(Vibrator) BaseApplication.getContext().getSystemService(Service.VIBRATOR_SERVICE);
  26. vibrator.vibrate(new long[]{0,time},-1);
  27. return true;
  28. }
  29. /**
  30. * 打开闪光灯
  31. * @return
  32. */
  33. @JavascriptInterface
  34. public boolean openFlashlight(){
  35. try{
  36. camera= Camera.open();
  37. if(camera!=null){
  38. camera.startPreview();
  39. Camera.Parameters parameters=camera.getParameters();
  40. parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
  41. camera.setParameters(parameters);
  42. return true;
  43. }
  44. return false;
  45. }catch (Exception e){
  46. return false;
  47. }
  48. }
  49. /**
  50. * 关闭闪光灯
  51. * @return
  52. */
  53. @JavascriptInterface
  54. public boolean closeFlashlight(){
  55. if(camera!=null){
  56. camera.getParameters().setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
  57. camera.setParameters(camera.getParameters());
  58. camera.stopPreview();
  59. camera.release();
  60. camera=null;
  61. return true;
  62. }else{
  63. return false;
  64. }
  65. }
  66. /**
  67. * 取得设备位置信息
  68. * @return
  69. */
  70. @JavascriptInterface
  71. public String getPosition(){
  72. LocationManager locationManager=(LocationManager) BaseApplication.getContext().getSystemService(Context.LOCATION_SERVICE);
  73. //获取可用的位置提供器
  74. String locationProvider;
  75. List<String> providers=locationManager.getProviders(true);
  76. if(providers.contains(locationManager.GPS_PROVIDER)){
  77. locationProvider=locationManager.GPS_PROVIDER;
  78. }else if(providers.contains(locationManager.NETWORK_PROVIDER)){
  79. locationProvider=locationManager.NETWORK_PROVIDER;
  80. }else{
  81. return "找不到地理位置获取设备";
  82. }
  83. if (ContextCompat.checkSelfPermission(BaseApplication.getContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
  84. || ContextCompat.checkSelfPermission(BaseApplication.getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED){
  85. Location location=locationManager.getLastKnownLocation(locationProvider);
  86. if(location!=null){
  87. return "{longitude:"+location.getLongitude()+",latitude"+location.getLatitude()+"}";
  88. }else{
  89. return "获取地理位置失败";
  90. }
  91. }else {
  92. return "没有权限获取该设备地理位置";
  93. }
  94. }
  95. @JavascriptInterface
  96. public void toast(String msg){
  97. Toast.makeText(BaseApplication.getContext(),msg,Toast.LENGTH_LONG).show();
  98. }
  99. }
  1. package com.jspp.sdxjwkq.js;
  2. import android.webkit.JavascriptInterface;
  3. import org.json.JSONArray;
  4. import org.json.JSONObject;
  5. import java.io.File;
  6. /**
  7. * 文件操作
  8. */
  9. public class FileSystem {
  10. public String DirRoot="/mnt/sdcard";//文件系统的根
  11. /**
  12. * 创建文件夹
  13. * @param url(文件夹路径)
  14. * @return
  15. */
  16. @JavascriptInterface
  17. public boolean createDirByUrl(String url){
  18. File file=new File(this.DirRoot+url);
  19. if(!file.exists()){
  20. file.mkdirs();
  21. return true;
  22. }else{
  23. return false;
  24. }
  25. }
  26. /**
  27. * 文件是否存在
  28. * @param url
  29. * @return
  30. */
  31. @JavascriptInterface
  32. public boolean fileExists(String url){
  33. File file=new File(this.DirRoot+url);
  34. return file.exists();
  35. }
  36. /**
  37. * 返回文件列表
  38. * @param url
  39. * @return
  40. */
  41. @JavascriptInterface
  42. public String getFileListByUrl(String url){
  43. try{
  44. JSONArray jsonArray=new JSONArray();
  45. File file=new File(this.DirRoot+url);
  46. File[] subFile=file.listFiles();
  47. for(int i=0;i<subFile.length;i++){
  48. JSONObject jsonObject=new JSONObject();
  49. jsonObject.put("name",subFile[i].getName());//文件名
  50. jsonObject.put("path",subFile[i].getPath());//文件路径
  51. if(subFile[i].isDirectory()){//文件类型
  52. jsonObject.put("type","dir");
  53. }else{
  54. jsonObject.put("type","file");
  55. }
  56. jsonObject.put("size",subFile[i].length());
  57. jsonArray.put(i,jsonObject);
  58. }
  59. return jsonArray.toString();
  60. }catch (Exception e){return "error";}
  61. }
  62. }

可以看到每一个类前面都要引入android.webkit.JavascriptInterface这个包,还有就是方法都要是public的,前面标注上@JavascriptInterface,声明为JavaScript接口。

最后就是在相应的webview控件里面暴露这些接口啦,例如下面代码

  1. package com.jspp.sdxjwkq.js;
  2. import android.content.Context;
  3. import android.net.Uri;
  4. import android.os.Bundle;
  5. import android.support.v4.app.Fragment;
  6. import android.view.KeyEvent;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.webkit.WebView;
  11. import android.webkit.WebViewClient;
  12. /**
  13. * 软件列表
  14. */
  15. public class AppFragment extends Fragment {
  16. private static WebView webView;
  17. /**
  18. * 在这里写页面逻辑
  19. * @param savedInstanceState
  20. */
  21. @Override
  22. public void onActivityCreated(Bundle savedInstanceState){
  23. super.onActivityCreated(savedInstanceState);
  24. webView=getView().findViewById(R.id.webView1);
  25. //新窗口使用webview
  26. webView.setWebViewClient(new WebViewClient(){
  27. @Override
  28. public boolean shouldOverrideUrlLoading(WebView view,String url){
  29. view.loadUrl(url);
  30. return true;
  31. }
  32. });
  33. webView.getSettings().setJavaScriptEnabled(true);//支持javascript
  34. //javascript接口映射
  35. webView.addJavascriptInterface(new Utils(), "Utils");
  36. webView.addJavascriptInterface(new Sql(), "Sql");
  37. webView.loadUrl("file:///mnt/sdcard/jspp/system/appList.html");
  38. }
  39. /**
  40. * 用户按下返回键
  41. * @param keyCode
  42. * @param event
  43. * @return
  44. */
  45. public static boolean onKeyDown(int keyCode, KeyEvent event){
  46. if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
  47. webView.goBack();
  48. return false;
  49. }
  50. return true;
  51. }
  52. // TODO: Rename parameter arguments, choose names that match
  53. // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  54. private static final String ARG_PARAM1 = "param1";
  55. private static final String ARG_PARAM2 = "param2";
  56. // TODO: Rename and change types of parameters
  57. private String mParam1;
  58. private String mParam2;
  59. private OnFragmentInteractionListener mListener;
  60. public AppFragment() {
  61. // Required empty public constructor
  62. }
  63. /**
  64. * Use this factory method to create a new instance of
  65. * this fragment using the provided parameters.
  66. *
  67. * @param param1 Parameter 1.
  68. * @param param2 Parameter 2.
  69. * @return A new instance of fragment AppFragment.
  70. */
  71. // TODO: Rename and change types and number of parameters
  72. public static AppFragment newInstance(String param1, String param2) {
  73. AppFragment fragment = new AppFragment();
  74. Bundle args = new Bundle();
  75. args.putString(ARG_PARAM1, param1);
  76. args.putString(ARG_PARAM2, param2);
  77. fragment.setArguments(args);
  78. return fragment;
  79. }
  80. @Override
  81. public void onCreate(Bundle savedInstanceState) {
  82. super.onCreate(savedInstanceState);
  83. if (getArguments() != null) {
  84. mParam1 = getArguments().getString(ARG_PARAM1);
  85. mParam2 = getArguments().getString(ARG_PARAM2);
  86. }
  87. }
  88. @Override
  89. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  90. Bundle savedInstanceState) {
  91. // Inflate the layout for this fragment
  92. return inflater.inflate(R.layout.fragment_app, container, false);
  93. }
  94. // TODO: Rename method, update argument and hook method into UI event
  95. public void onButtonPressed(Uri uri) {
  96. if (mListener != null) {
  97. mListener.onFragmentInteraction(uri);
  98. }
  99. }
  100. //用于页面间通信
  101. @Override
  102. public void onAttach(Context context) {
  103. super.onAttach(context);
  104. if (context instanceof OnFragmentInteractionListener) {
  105. mListener = (OnFragmentInteractionListener) context;
  106. } else {
  107. // throw new RuntimeException(context.toString()
  108. // + " must implement OnFragmentInteractionListener");
  109. }
  110. }
  111. @Override
  112. public void onDetach() {
  113. super.onDetach();
  114. mListener = null;
  115. }
  116. /**
  117. * This interface must be implemented by activities that contain this
  118. * fragment to allow an interaction in this fragment to be communicated
  119. * to the activity and potentially other fragments contained in that
  120. * activity.
  121. * <p>
  122. * See the Android Training lesson <a href=
  123. * "http://developer.android.com/training/basics/fragments/communicating.html"
  124. * >Communicating with Other Fragments</a> for more information.
  125. */
  126. public interface OnFragmentInteractionListener {
  127. // TODO: Update argument type and name
  128. void onFragmentInteraction(Uri uri);
  129. }
  130. }

 //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/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

3 0
收藏该文
已收藏

评论内容:(最多支持255个字符)