WebViewActivity.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. package com.qingdaofushan.home.weiview;
  2. import android.Manifest;
  3. import android.annotation.TargetApi;
  4. import android.app.Activity;
  5. import android.content.ClipData;
  6. import android.content.ContentValues;
  7. import android.content.Intent;
  8. import android.content.pm.PackageManager;
  9. import android.content.pm.ResolveInfo;
  10. import android.graphics.Bitmap;
  11. import android.icu.text.SimpleDateFormat;
  12. import android.net.Uri;
  13. import android.os.Build;
  14. import android.os.Bundle;
  15. import android.os.Environment;
  16. import android.provider.MediaStore;
  17. import android.util.Base64;
  18. import android.util.Log;
  19. import android.view.KeyEvent;
  20. import android.webkit.ValueCallback;
  21. import android.webkit.WebSettings;
  22. import android.webkit.WebView;
  23. import android.widget.LinearLayout;
  24. import android.widget.Toast;
  25. import androidx.annotation.NonNull;
  26. import androidx.annotation.Nullable;
  27. import androidx.appcompat.app.AppCompatActivity;
  28. import androidx.core.app.ActivityCompat;
  29. import androidx.core.content.ContextCompat;
  30. import androidx.core.content.FileProvider;
  31. import androidx.core.os.EnvironmentCompat;
  32. import com.just.agentweb.AgentWeb;
  33. import com.just.agentweb.PermissionInterceptor;
  34. import com.just.agentweb.WebChromeClient;
  35. import com.just.agentweb.WebViewClient;
  36. //import com.king.zxing.CameraScan;
  37. import com.qingdaofushan.home.activity.CamActivity;
  38. import com.qingdaofushan.home.event.EventData;
  39. import com.qingdaofushan.home.R;
  40. import com.qingdaofushan.home.utils.ToastUtil;
  41. import com.qingdaofushan.home.utils.Uri2PathUtil;
  42. import com.qingdaofushan.home.zxing.view.Constant;
  43. import org.greenrobot.eventbus.EventBus;
  44. import org.greenrobot.eventbus.Subscribe;
  45. import org.greenrobot.eventbus.ThreadMode;
  46. import java.io.File;
  47. import java.io.FileInputStream;
  48. import java.io.FileNotFoundException;
  49. import java.io.IOException;
  50. import java.io.InputStream;
  51. import java.util.Date;
  52. import java.util.List;
  53. import java.util.Locale;
  54. /**
  55. * @Author pwxmax
  56. * @Date 2020.6.11
  57. * @Discription 对接H5通用的 Activity
  58. */
  59. public class WebViewActivity extends AppCompatActivity {
  60. LinearLayout linearLayout;
  61. protected AgentWeb mAgentWeb;
  62. private String url;
  63. private int REQUEST_CODE = 200;
  64. // 拍照的requestCode
  65. private static final int CAMERA_REQUEST_CODE = 0x00000010;
  66. // 申请相机权限的requestCode
  67. private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
  68. /**
  69. * 用于保存拍照图片的uri
  70. */
  71. private Uri mCameraUri;
  72. /**
  73. * 用于保存图片的文件路径,Android 10以下使用图片路径访问图片
  74. */
  75. private String mCameraImagePath;
  76. /**
  77. * 是否是Android 10以上手机
  78. */
  79. private boolean isAndroidQ = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
  80. private ValueCallback<Uri> uploadMessage;
  81. private ValueCallback<Uri[]> uploadMessageAboveL;
  82. private final static int FILE_CHOOSER_RESULT_CODE = 10000;
  83. @Override
  84. protected void onCreate(@Nullable Bundle savedInstanceState) {
  85. super.onCreate(savedInstanceState);
  86. setContentView(R.layout.activity_web);
  87. EventBus.getDefault().register(this);
  88. initView();
  89. }
  90. private void initView() {
  91. url = getIntent().getStringExtra("url");
  92. // url="http://192.168.1.11:8080";
  93. linearLayout = findViewById(R.id.ll_webview);
  94. AndroidWebView.assistActivity(this);
  95. mAgentWeb = AgentWeb.with(this)
  96. .setAgentWebParent(linearLayout, new LinearLayout.LayoutParams(-1, -1))
  97. .closeIndicator()
  98. .setWebChromeClient(mWebChromeClient)
  99. .setWebViewClient(mWebViewClient)
  100. // .setPermissionInterceptor(mPermissionInterceptor)
  101. .createAgentWeb()
  102. .go(url);
  103. if (mAgentWeb != null) {
  104. mAgentWeb.getJsInterfaceHolder().addJavaObject("android", new AndroidInterface(mAgentWeb, this));
  105. //注入对象
  106. WebSettings webSettings = mAgentWeb.getAgentWebSettings().getWebSettings();
  107. webSettings.setUseWideViewPort(true);//关键点
  108. webSettings.setDomStorageEnabled(true);
  109. webSettings.setDefaultTextEncodingName("UTF-8");
  110. webSettings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true
  111. webSettings.setLoadWithOverviewMode(true);
  112. webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
  113. webSettings.setBuiltInZoomControls(false); // 设置显示缩放按钮
  114. // webSettings.setAppCacheEnabled(true);//是否使用缓存
  115. webSettings.setSupportZoom(false); // 支持缩放
  116. webSettings.setAllowFileAccess(true); //允许加载本地文件html file协议, 这可能会造成不安全 , 建议重写关闭
  117. webSettings.setAllowFileAccessFromFileURLs(true); //通过 file url 加载的 Javascript 读取其他的本地文件 .建议关闭
  118. webSettings.setAllowUniversalAccessFromFileURLs(true);//允许通过 file url 加载的 Javascript 可以访问其他的源,包括其他的文件和 http,https 等其他的源
  119. mAgentWeb.getWebCreator().getWebView().setOverScrollMode(WebView.OVER_SCROLL_NEVER);
  120. }
  121. }
  122. protected PermissionInterceptor mPermissionInterceptor = new PermissionInterceptor() {
  123. /**
  124. * PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
  125. * @param url
  126. * @param permissions
  127. * @param action
  128. * @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
  129. */
  130. @Override
  131. public boolean intercept(String url, String[] permissions, String action) {
  132. //Log.i(TAG, "mUrl:" + url + " permission:" + mGson.toJson(permissions) + " action:" + action);
  133. return false;
  134. }
  135. };
  136. private WebViewClient mWebViewClient = new WebViewClient() {
  137. @Override
  138. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  139. //do you work
  140. }
  141. };
  142. private WebChromeClient mWebChromeClient = new WebChromeClient() {
  143. @Override
  144. public void onProgressChanged(WebView view, int newProgress) {
  145. //do you work
  146. }
  147. // For Android < 3.0
  148. public void openFileChooser(ValueCallback<Uri> valueCallback) {
  149. uploadMessage = valueCallback;
  150. openImageChooserActivity();
  151. }
  152. // For Android >= 3.0
  153. public void openFileChooser(ValueCallback valueCallback, String acceptType) {
  154. uploadMessage = valueCallback;
  155. openImageChooserActivity();
  156. }
  157. //For Android >= 4.1
  158. public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
  159. uploadMessage = valueCallback;
  160. openImageChooserActivity();
  161. }
  162. // For Android >= 5.0
  163. @Override
  164. public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
  165. uploadMessageAboveL = filePathCallback;
  166. openImageChooserActivity();
  167. return true;
  168. }
  169. };
  170. // 2.回调方法触发本地选择文件
  171. private void openImageChooserActivity() {
  172. // checkPermissionAndCamera();
  173. Intent i = new Intent(Intent.ACTION_GET_CONTENT);
  174. i.addCategory(Intent.CATEGORY_OPENABLE);
  175. i.setType("image/*");//图片上传
  176. // i.setType("file/*");//文件上传
  177. // i.setType("*/*");//文件上传
  178. startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_RESULT_CODE);
  179. }
  180. @Override
  181. public boolean onKeyDown(int keyCode, KeyEvent event) {
  182. if (mAgentWeb.handleKeyEvent(keyCode, event)) {
  183. return true;
  184. }
  185. if (keyCode == KeyEvent.KEYCODE_BACK) {
  186. }
  187. return super.onKeyDown(keyCode, event);
  188. }
  189. @Override
  190. protected void onPause() {
  191. mAgentWeb.getWebLifeCycle().onPause();
  192. super.onPause();
  193. }
  194. // @Override
  195. // protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  196. // super.onActivityResult(requestCode, resultCode, data);
  197. // /**
  198. // * 处理二维码扫描结果
  199. // */
  200. // if (resultCode == RESULT_OK) {
  201. // switch (requestCode) {
  202. // case 200:
  203. // Bundle bundle = data.getExtras();
  204. // String scanResult = bundle.getString(Constant.INTENT_EXTRA_KEY_QR_SCAN);
  205. //// String result = CameraScan.parseScanResult(data);
  206. // mAgentWeb.getJsAccessEntrace().quickCallJs("QRCode", scanResult);
  207. // break;
  208. // case CAMERA_REQUEST_CODE:
  209. // if (uploadMessageAboveL != null) {
  210. // Uri[] results = new Uri[]{mCameraUri};
  211. // uploadMessageAboveL.onReceiveValue(results);
  212. // uploadMessageAboveL = null;
  213. //// onActivityResultAboveL(requestCode, resultCode, data);
  214. // } else if (uploadMessage != null) {
  215. // uploadMessage.onReceiveValue(mCameraUri);
  216. // uploadMessage = null;
  217. // }
  218. //// String uploadpath = Uri2PathUtil.getRealPathFromUri(this, mCameraUri);
  219. //// mAgentWeb.getJsAccessEntrace().quickCallJs("Camera", uploadpath);
  220. // break;
  221. // }
  222. // } else {
  223. // //这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了
  224. // //WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值
  225. // //否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效
  226. // if (uploadMessage != null) {
  227. // uploadMessage.onReceiveValue(null);
  228. // uploadMessage = null;
  229. // } else if (uploadMessageAboveL != null) {
  230. // uploadMessageAboveL.onReceiveValue(null);
  231. // uploadMessageAboveL = null;
  232. // }
  233. // }
  234. // }
  235. //
  236. // // 3.选择图片后处理
  237. @Override
  238. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  239. super.onActivityResult(requestCode, resultCode, data);
  240. if (requestCode == FILE_CHOOSER_RESULT_CODE) {
  241. if (null == uploadMessage && null == uploadMessageAboveL) return;
  242. Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
  243. // Uri result = (((data == null) || (resultCode != RESULT_OK)) ? null : data.getData());
  244. if (uploadMessageAboveL != null) {
  245. onActivityResultAboveL(requestCode, resultCode, data);
  246. } else if (uploadMessage != null) {
  247. uploadMessage.onReceiveValue(result);
  248. uploadMessage = null;
  249. }
  250. } else {
  251. //这里uploadMessage跟uploadMessageAboveL在不同系统版本下分别持有了
  252. //WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值
  253. //否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效
  254. if (uploadMessage != null) {
  255. uploadMessage.onReceiveValue(null);
  256. uploadMessage = null;
  257. } else if (uploadMessageAboveL != null) {
  258. uploadMessageAboveL.onReceiveValue(null);
  259. uploadMessageAboveL = null;
  260. }
  261. }
  262. }
  263. // 4. 选择内容回调到Html页面
  264. @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  265. private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
  266. if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
  267. return;
  268. Uri[] results = null;
  269. if (resultCode == Activity.RESULT_OK) {
  270. if (intent != null) {
  271. String dataString = intent.getDataString();
  272. ClipData clipData = intent.getClipData();
  273. if (clipData != null) {
  274. results = new Uri[clipData.getItemCount()];
  275. for (int i = 0; i < clipData.getItemCount(); i++) {
  276. ClipData.Item item = clipData.getItemAt(i);
  277. results[i] = item.getUri();
  278. }
  279. }
  280. if (dataString != null)
  281. results = new Uri[]{Uri.parse(dataString)};
  282. }
  283. }
  284. uploadMessageAboveL.onReceiveValue(results);
  285. uploadMessageAboveL = null;
  286. }
  287. @Subscribe(threadMode = ThreadMode.MAIN)
  288. public void stopServiceEvent(EventData eventData) {
  289. if (eventData.getCode() == 1) {
  290. mAgentWeb.getJsAccessEntrace().quickCallJs("StartService", "1");
  291. } else if (eventData.getCode() == 2) {
  292. mAgentWeb.getJsAccessEntrace().quickCallJs("StartService", "2");
  293. } else if (eventData.getCode() == 3) {
  294. checkPermissionAndCamera();
  295. }
  296. }
  297. /**
  298. * 检查权限并拍照。
  299. * 调用相机前先检查权限。
  300. */
  301. private void checkPermissionAndCamera() {
  302. int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(),
  303. Manifest.permission.CAMERA);
  304. if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) {
  305. //有权限,调起相机拍照。
  306. openCamera();
  307. } else {
  308. //没有权限,申请权限。
  309. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
  310. PERMISSION_CAMERA_REQUEST_CODE);
  311. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
  312. PERMISSION_CAMERA_REQUEST_CODE);
  313. }
  314. }
  315. /**
  316. * 处理权限申请的回调。
  317. *
  318. * @param requestCode
  319. * @param permissions
  320. * @param grantResults
  321. */
  322. @Override
  323. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  324. if (requestCode == PERMISSION_CAMERA_REQUEST_CODE) {
  325. if (grantResults.length > 0
  326. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  327. //允许权限,有调起相机拍照。
  328. openCamera();
  329. } else {
  330. //拒绝权限,弹出提示框。
  331. Toast.makeText(this, "拍照权限被拒绝", Toast.LENGTH_LONG).show();
  332. }
  333. }
  334. }
  335. /**
  336. * 调起相机拍照
  337. */
  338. private void openCamera() {
  339. Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  340. // 判断是否有相机
  341. if (captureIntent.resolveActivity(getPackageManager()) != null) {
  342. File photoFile = null;
  343. Uri photoUri = null;
  344. if (isAndroidQ) {
  345. // 适配android 10
  346. photoUri = createImageUri();
  347. } else {
  348. try {
  349. photoFile = createImageFile();
  350. } catch (IOException e) {
  351. e.printStackTrace();
  352. }
  353. if (photoFile != null) {
  354. mCameraImagePath = photoFile.getAbsolutePath();
  355. System.out.println("path = " + mCameraImagePath);
  356. photoUri = FileProvider.getUriForFile(WebViewActivity.this,
  357. "com.qingdaofushan.home.fileprovider", photoFile);
  358. }
  359. }
  360. System.out.println("photoUri = " + photoUri);
  361. mCameraUri = photoUri;
  362. if (photoUri != null) {
  363. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
  364. List<ResolveInfo> resInfoList = getPackageManager()
  365. .queryIntentActivities(captureIntent, PackageManager.MATCH_DEFAULT_ONLY);
  366. for (ResolveInfo resolveInfo : resInfoList) {
  367. String packageName = resolveInfo.activityInfo.packageName;
  368. grantUriPermission(packageName, photoUri,
  369. Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
  370. }
  371. }
  372. captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
  373. captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  374. startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);
  375. }
  376. }
  377. }
  378. /**
  379. * 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法
  380. *
  381. * @return 图片的uri
  382. */
  383. private Uri createImageUri() {
  384. //设置保存参数到ContentValues中
  385. ContentValues contentValues = new ContentValues();
  386. //设置文件名
  387. contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis() + "");
  388. //兼容Android Q和以下版本
  389. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  390. //android Q中不再使用DATA字段,而用RELATIVE_PATH代替
  391. //TODO RELATIVE_PATH是相对路径不是绝对路径;照片存储的地方为:内部存储/Pictures/preventpro
  392. contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/preventpro");
  393. }
  394. //设置文件类型
  395. contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/JPEG");
  396. //执行insert操作,向系统文件夹中添加文件
  397. //EXTERNAL_CONTENT_URI代表外部存储器,该值不变
  398. Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
  399. return uri;
  400. }
  401. /**
  402. * 创建保存图片的文件
  403. *
  404. * @return
  405. * @throws IOException
  406. */
  407. private File createImageFile() throws IOException {
  408. String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss",
  409. Locale.getDefault()).format(new Date()) + ".jpg";
  410. // File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
  411. // File storageDir = Environment.getExternalStoragePublicDirectory(
  412. // Environment.DIRECTORY_PICTURES);
  413. File storageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
  414. + File.separator + "Pictures" + File.separator + "abc");
  415. if (!storageDir.exists()) storageDir.mkdirs();
  416. File tempFile = new File(storageDir, imageName);
  417. if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {
  418. return null;
  419. }
  420. return tempFile;
  421. }
  422. /**
  423. * 文件转base64字符串
  424. *
  425. * @param file
  426. * @return
  427. */
  428. public String fileToBase64(File file) {
  429. String base64 = null;
  430. InputStream in = null;
  431. try {
  432. in = new FileInputStream(file);
  433. byte[] bytes = new byte[in.available()];
  434. int length = in.read(bytes);
  435. base64 = Base64.encodeToString(bytes, 0, length, Base64.DEFAULT);
  436. } catch (FileNotFoundException e) {
  437. // TODO Auto-generated catch block
  438. ToastUtil.showToast("文件读取异常");
  439. } catch (IOException e) {
  440. // TODO Auto-generated catch block
  441. ToastUtil.showToast("IO读取异常");
  442. } finally {
  443. try {
  444. if (in != null) {
  445. in.close();
  446. }
  447. } catch (IOException e) {
  448. // TODO Auto-generated catch block
  449. ToastUtil.showToast("IO关闭异常");
  450. }
  451. }
  452. return base64;
  453. }
  454. @Override
  455. protected void onResume() {
  456. mAgentWeb.getWebLifeCycle().onResume();
  457. super.onResume();
  458. }
  459. @Override
  460. public void onDestroy() {
  461. super.onDestroy();
  462. mAgentWeb.getWebLifeCycle().onDestroy();
  463. EventBus.getDefault().unregister(this);
  464. }
  465. }