最近在开发过程中遇到一个问题,主要是调用第三方的实名认证,需要拍照和录像;

办过支付宝大宝卡和腾讯的大王卡的都知道这玩意,办卡的时候就需要进行实名认证,人脸识别;

本来第三方平台(xxx流量公司)说的是直接用WebView加载这个H5界面就完事了,我心想这么简单,那不是分分钟的事,放着后面做(公司就我一个安卓,所以开发都是我说的算_,独立开发有的时候还是挺爽);

结果到项目快要上线的时候,只想说一句mmp,根本调不了相机,这个时候怎么搞,只有自己去实现了,才发现自己已经进了webview的深坑;

到处找资料,发现webview根本不能让h5自己调用,ios是可以的,项目经理就说是我的锅,真特么又一句mmp(关键是这个H5还特么不能改,不能提供给我调用的方法);

进入正题,首先来了解webview,这里我分享两篇大佬的博客

1,WebView开车指南
2,WebView详解

看完这两篇基本你已经可以随意操作webview了, 但是,当你调用相机的时候你才发现这只是入坑的开始

第一个坑

调用相机之后,文件回调不了,其实根本就是没有回调.这个时候你要去检查你的webview的Settings了关键代码,是否给足了权限;

 WebSettings settings = webView.getSettings();settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);settings.setDomStorageEnabled(true);settings.setDefaultTextEncodingName("UTF-8");settings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 truesettings.setAllowFileAccess(true);    // 是否可访问本地文件,默认值 true// 是否允许通过file url加载的Javascript读取本地文件,默认值 falsesettings.setAllowFileAccessFromFileURLs(false);// 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 falsesettings.setAllowUniversalAccessFromFileURLs(false);//开启JavaScript支持settings.setJavaScriptEnabled(true);// 支持缩放settings.setSupportZoom(true);

其中settings.setDomStorageEnabled(true);这个方法当时我没加,血崩了一次;

第二个坑

WebChromeClient的openFileChooser()只调用了一次

首先了解为什么这个方法只调用了一次,看这篇博客就可

Android开发深入理解WebChromeClient之onShowFileChooser或openFileChooser使用说明

看了他基本你就了解怎么回事了

第三个坑

怎么区分是要调用相机是需要拍照还是录视频
这个时候你就要看WebViewClient的 shouldOverrideUrlLoading()方法了,我是通过拦截url来判断url里面是拍照还是录制视频来加一个flag
这样你调用你的相机的时候就可以分别处理了

第四个坑

android 7.0的FileProvider的坑
看洪阳大佬的这篇博客基本就了解了

Android 7.0 行为变更 通过FileProvider在应用间共享文件吧

最后附上我自己的代码吧

package com.sihaiwanlian.cmccnev.feature.verify.activitys;import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.support.annotation.RequiresApi;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;import com.orhanobut.logger.Logger;
import com.sihaiwanlian.cmccnev.R;
import com.sihaiwanlian.cmccnev.utils.PhotoUtils;import java.io.File;import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;public class Certifica extends AppCompatActivity {private final static String TAG = "villa";@BindView(R.id.titleBar_iv_back)ImageView mTitleBarIvBack;@BindView(R.id.titleBar_btn_back)Button mTitleBarBtnBack;@BindView(R.id.titleBar_centerTV)TextView mTitleBarCenterTV;private WebView webView;private ValueCallback<Uri> mUploadMessage;private ValueCallback<Uri[]> mUploadCallbackAboveL;private final static int PHOTO_REQUEST = 100;private final static int VIDEO_REQUEST = 120;private final static String url = "your_url";private boolean videoFlag = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_certifica);ButterKnife.bind(this);initToolBar();initWebView();}private void initToolBar() {mTitleBarCenterTV.setText("实名认证");}//初始化webViewprivate void initWebView() {//从布局文件中扩展webView  webView = (WebView) this.findViewById(R.id.certifi_webview);initWebViewSetting();}//初始化webViewSetting@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)private void initWebViewSetting() {WebSettings settings = webView.getSettings();settings.setUseWideViewPort(true);settings.setLoadWithOverviewMode(true);settings.setDomStorageEnabled(true);settings.setDefaultTextEncodingName("UTF-8");settings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 truesettings.setAllowFileAccess(true);    // 是否可访问本地文件,默认值 true// 是否允许通过file url加载的Javascript读取本地文件,默认值 falsesettings.setAllowFileAccessFromFileURLs(false);// 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 falsesettings.setAllowUniversalAccessFromFileURLs(false);//开启JavaScript支持settings.setJavaScriptEnabled(true);// 支持缩放settings.setSupportZoom(true);//辅助WebView设置处理关于页面跳转,页面请求等操作webView.setWebViewClient(new MyWebViewClient());//辅助WebView处理图片上传操作webView.setWebChromeClient(new MyChromeWebClient());//加载地址webView.loadUrl(url);}@OnClick(R.id.titleBar_btn_back)public void onViewClicked() {if (webView.canGoBack()) {webView.goBack();// 返回前一个页面} else {finish();}}//自定义 WebViewClient 辅助WebView设置处理关于页面跳转,页面请求等操作【处理tel协议和视频通讯请求url的拦截转发】private class MyWebViewClient extends WebViewClient {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {Logger.e(url);if (!TextUtils.isEmpty(url)) {videoFlag = url.contains("vedio");}if (url.trim().startsWith("tel")) {//特殊情况tel,调用系统的拨号软件拨号【<a href="tel:1111111111">1111111111</a>】Intent i = new Intent(Intent.ACTION_VIEW);i.setData(Uri.parse(url));startActivity(i);} else {String port = url.substring(url.lastIndexOf(":") + 1, url.lastIndexOf("/"));//尝试要拦截的视频通讯url格式(808端口):【http://xxxx:808/?roomName】if (port.equals("808")) {//特殊情况【若打开的链接是视频通讯地址格式则调用系统浏览器打开】Intent i = new Intent(Intent.ACTION_VIEW);i.setData(Uri.parse(url));startActivity(i);} else {//其它非特殊情况全部放行view.loadUrl(url);}}return true;}}private File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg");private Uri imageUri;//自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】public class MyChromeWebClient extends WebChromeClient {// For Android 3.0-  public void openFileChooser(ValueCallback<Uri> uploadMsg) {Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 3.0+  public void openFileChooser(ValueCallback uploadMsg, String acceptType) {Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}//For Android 4.1  public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadMessage = uploadMsg;if (videoFlag) {recordVideo();} else {takePhoto();}}// For Android 5.0+  public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {Log.d(TAG, "onShowFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");mUploadCallbackAboveL = filePathCallback;if (videoFlag) {recordVideo();} else {takePhoto();}return true;}}/*** 拍照*/private void takePhoto() {imageUri = Uri.fromFile(fileUri);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri = FileProvider.getUriForFile(Certifica.this, getPackageName() + ".fileprovider", fileUri);//通过FileProvider创建一个content类型的Uri}PhotoUtils.takePicture(Certifica.this, imageUri, PHOTO_REQUEST);}/*** 录像*/private void recordVideo() {Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//限制时长intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 10);//开启摄像机startActivityForResult(intent, VIDEO_REQUEST);}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {//如果按下的是回退键且历史记录里确实还有页面if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {webView.goBack();return true;}return super.onKeyDown(keyCode, event);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == PHOTO_REQUEST) {if (null == mUploadMessage && null == mUploadCallbackAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();if (mUploadCallbackAboveL != null) {onActivityResultAboveL(requestCode, resultCode, data);} else if (mUploadMessage != null) {mUploadMessage.onReceiveValue(result);mUploadMessage = null;}} else if (requestCode == VIDEO_REQUEST) {if (null == mUploadMessage && null == mUploadCallbackAboveL) return;Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();if (mUploadCallbackAboveL != null) {if (resultCode == RESULT_OK) {mUploadCallbackAboveL.onReceiveValue(new Uri[]{result});mUploadCallbackAboveL = null;} else {mUploadCallbackAboveL.onReceiveValue(new Uri[]{});mUploadCallbackAboveL = null;}} else if (mUploadMessage != null) {if (resultCode == RESULT_OK) {mUploadMessage.onReceiveValue(result);mUploadMessage = null;} else {mUploadMessage.onReceiveValue(Uri.EMPTY);mUploadMessage = null;}}}}@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null) {return;}Uri[] results = null;if (resultCode == Activity.RESULT_OK) {if (data == null) {results = new Uri[]{imageUri};} else {String dataString = data.getDataString();ClipData clipData = data.getClipData();if (clipData != null) {results = new Uri[clipData.getItemCount()];for (int i = 0; i < clipData.getItemCount(); i++) {ClipData.Item item = clipData.getItemAt(i);results[i] = item.getUri();}}if (dataString != null)results = new Uri[]{Uri.parse(dataString)};}}mUploadCallbackAboveL.onReceiveValue(results);mUploadCallbackAboveL = null;}@Overrideprotected void onDestroy() {super.onDestroy();if (webView != null) {webView.setWebViewClient(null);webView.setWebChromeClient(null);webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);webView.clearHistory();
//            ((ViewGroup) webView.getParent()).removeView(webView);webView.destroy();webView = null;}}
}

这里面有个photoUtils,已经封装好了各种调用,简单好用

public class PhotoUtils {private static final String TAG = "PhotoUtils";/*** @param activity    当前activity* @param imageUri    拍照后照片存储路径* @param requestCode 调用系统相机请求码*/public static void takePicture(Activity activity, Uri imageUri, int requestCode) {//调用系统相机Intent intentCamera = new Intent();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件}intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//将拍照结果保存至photo_file的Uri中,不保留在相册中intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);if (activity!=null){activity.startActivityForResult(intentCamera, requestCode);}}/*** @param activity    当前activity* @param requestCode 打开相册的请求码*/public static void openPic(Activity activity, int requestCode) {Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);photoPickerIntent.setType("image/*");activity.startActivityForResult(photoPickerIntent, requestCode);}/*** @param activity    当前activity* @param orgUri      剪裁原图的Uri* @param desUri      剪裁后的图片的Uri* @param aspectX     X方向的比例* @param aspectY     Y方向的比例* @param width       剪裁图片的宽度* @param height      剪裁图片高度* @param requestCode 剪裁图片的请求码*/public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) {Intent intent = new Intent("com.android.camera.action.CROP");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);}intent.setDataAndType(orgUri, "image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", aspectX);intent.putExtra("aspectY", aspectY);intent.putExtra("outputX", width);intent.putExtra("outputY", height);intent.putExtra("scale", true);//将剪切的图片保存到目标Uri中intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri);intent.putExtra("return-data", false);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true);activity.startActivityForResult(intent, requestCode);}/*** 读取uri所在的图片** @param uri      图片对应的Uri* @param mContext 上下文对象* @return 获取图像的Bitmap*/public static Bitmap getBitmapFromUri(Uri uri, Context mContext) {try {
//            Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), uri);Bitmap bitmapFormUri = getBitmapFormUri(mContext, uri);return bitmapFormUri;} catch (Exception e) {e.printStackTrace();return null;}}/*** 通过uri获取图片并进行压缩** @param uri*/public static Bitmap getBitmapFormUri(Context ac, Uri uri) throws FileNotFoundException, IOException {InputStream input = ac.getContentResolver().openInputStream(uri);BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();onlyBoundsOptions.inJustDecodeBounds = true;onlyBoundsOptions.inDither = true;//optionalonlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optionalBitmapFactory.decodeStream(input, null, onlyBoundsOptions);input.close();int originalWidth = onlyBoundsOptions.outWidth;int originalHeight = onlyBoundsOptions.outHeight;if ((originalWidth == -1) || (originalHeight == -1)){return null;}//图片分辨率以480x800为标准float hh = 800f;//这里设置高度为800ffloat ww = 480f;//这里设置宽度为480f//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可int be = 1;//be=1表示不缩放if (originalWidth > originalHeight && originalWidth > ww) {//如果宽度大的话根据宽度固定大小缩放be = (int) (originalWidth / ww);} else if (originalWidth < originalHeight && originalHeight > hh) {//如果高度高的话根据宽度固定大小缩放be = (int) (originalHeight / hh);}if (be <= 0){be = 1;}//比例压缩BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = be;//设置缩放比例bitmapOptions.inDither = true;//optionalbitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optionalinput = ac.getContentResolver().openInputStream(uri);Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);input.close();return compressImage(bitmap);//再进行质量压缩}/*** 质量压缩方法** @param image* @return*/public static Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中int options = 100;while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩baos.reset();//重置baos即清空baos//第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中options -= 10;//每次都减少10}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片return bitmap;}/*** @param context 上下文对象* @param uri     当前相册照片的Uri* @return 解析后的Uri对应的String*/@SuppressLint("NewApi")public static String getPath(final Context context, final Uri uri) {final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;String pathHead = "file:///";// DocumentProviderif (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {// ExternalStorageProviderif (isExternalStorageDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];if ("primary".equalsIgnoreCase(type)) {return pathHead + Environment.getExternalStorageDirectory() + "/" + split[1];}}// DownloadsProviderelse if (isDownloadsDocument(uri)) {final String id = DocumentsContract.getDocumentId(uri);final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));return pathHead + getDataColumn(context, contentUri, null, null);}// MediaProviderelse if (isMediaDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];Uri contentUri = null;if ("image".equals(type)) {contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ("video".equals(type)) {contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ("audio".equals(type)) {contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}final String selection = "_id=?";final String[] selectionArgs = new String[]{split[1]};return pathHead + getDataColumn(context, contentUri, selection, selectionArgs);}}// MediaStore (and general)else if ("content".equalsIgnoreCase(uri.getScheme())) {return pathHead + getDataColumn(context, uri, null, null);}// Fileelse if ("file".equalsIgnoreCase(uri.getScheme())) {return pathHead + uri.getPath();}return null;}/*** Get the value of the data column for this Uri. This is useful for* MediaStore Uris, and other file-based ContentProviders.** @param context       The context.* @param uri           The Uri to query.* @param selection     (Optional) Filter used in the query.* @param selectionArgs (Optional) Selection arguments used in the query.* @return The value of the _data column, which is typically a file path.*/private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {Cursor cursor = null;final String column = "_data";final String[] projection = {column};try {cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);if (cursor != null && cursor.moveToFirst()) {final int column_index = cursor.getColumnIndexOrThrow(column);return cursor.getString(column_index);}} finally {if (cursor != null){cursor.close();}}return null;}/*** @param uri The Uri to check.* @return Whether the Uri authority is ExternalStorageProvider.*/private static boolean isExternalStorageDocument(Uri uri) {return "com.android.externalstorage.documents".equals(uri.getAuthority());}/*** @param uri The Uri to check.* @return Whether the Uri authority is DownloadsProvider.*/private static boolean isDownloadsDocument(Uri uri) {return "com.android.providers.downloads.documents".equals(uri.getAuthority());}/*** @param uri The Uri to check.* @return Whether the Uri authority is MediaProvider.*/private static boolean isMediaDocument(Uri uri) {return "com.android.providers.media.documents".equals(uri.getAuthority());}}

--------------------- 
原文:https://blog.csdn.net/villa_mou/article/details/78728417

深坑之Webview,解决H5调用android相机拍照和录像相关推荐

  1. 解决三星调用系统相机拍照显示图片旋转90度横着的问题

    最近项目有个功能是调用系统相机拍照上传图片的功能,发现别的手机都没有ok,只有三星的显示图片很明显是旋转了90度,横着的.后来百度了解是三星对android相机单独做了优化(android碎片化,各种 ...

  2. android 三星手机拍照旋转90度,解决三星调用系统相机拍照显示图片旋转90度横着的问题...

    /** * 调用系统相机拍照工具类 * @author yao * */ public class CaremaUtil { private static String strImgPath = &q ...

  3. FileReader()读取文件,h5调用原生相机拍照,FormData()上传服务器

    公司最近在做一个h5嵌入原生的项目,其中有一个需求是在没有和原生交互的前提下,调用调用手机相机进行拍照,然后将照片上传后端. 之前没接触过类似的需求,然后就感觉要调用移动端的硬件设备很是高大上:现在项 ...

  4. html5+php调用android手机图片,HTML5拍照上传图片Phonegap封装HTML5调用Android相机拍照上传到PHP端...

    HTML5拍照: 参考网址:http://blog.csdn.net/hfahe/article/details/7354912 上传部分也可以用ajax: $.ajax({ url: 'http:/ ...

  5. flutter获取Android照片,Flutter调用Android相机拍照及选取本地相册并渲染

    import 'package:flutter/material.dart'; //导入拍照插件 import 'package:image_picker/image_picker.dart'; // ...

  6. android webview中h5调用 拍照/相册 通用支持代码

    android webview中h5调用 拍照/相册 通用支持代码. 在webview的   WebChromeClient 中,重写 // For Android >= 5.0 @Overri ...

  7. h5前端调用android拍照功能,H5调用Android拍照和摄像以及选取相册

    之前一直认为H5调用Android,H5不需要Android配合能直接实现功能.前段时间,自己做这个功能,才发现不是这么回事. H5编写 html文件里只需要标签即可实现代码,代码如下所示: 拍照 ο ...

  8. android 相机拍照返回,Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题...

    版权声明:本文为博主原创文章,未经博主允许不得转载. 正常情况下调用系统相机拍照: 如果拍照后点击的是"确定"图标,返回的resultCode = -1(Activity.RESU ...

  9. Android多层嵌套Fragment中调用系统相机拍照以及裁剪的相关问题解决

    多层嵌套Fragment中调用系统相机拍照.裁剪 最近公司项目有频繁使用相机拍照的需求,然后频繁的实际使用过程中遇到很多大大小小的坑,在此记录下. (ps.关于一些拍照后图片旋转.裁剪设置返回数据为t ...

最新文章

  1. 谁是全球最顶级AI实验室?DeepMind、OpenAI和FAIR霸榜前三
  2. 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java
  3. “jQuery风暴” 推荐及配套代码下载
  4. formZ Pro 9(3D绘图软件)中文版
  5. C++ OJ在线编程常见输入输出技巧与示例
  6. com.fasterxml.jackson将对象序列化成json时,出现在json里的属性名称是怎么来的
  7. java linux任务管理器_Linux系列教程(二十四)——Linux的系统管理
  8. AutoCAD打印设置
  9. mysql ssd优化测试_MySQL服务器SSD性能问题分析与测试
  10. 基于Java+Springmvc+vue+element实现大学生科技创新创业项目管理系统
  11. ContextCapture(Smart3D)资源汇总
  12. 小程序input聚焦事件_微信小程序input失焦异常
  13. 读计算机网络得学五笔吗,打破无聊难学 另类五笔学习方法
  14. 利用反射等离激元超表面的模拟光计算
  15. elasticsearch6.4.3实现搜索同义词
  16. android SwipeMenuLayout实现控件侧滑删除
  17. 性能测试培训:性能瓶颈分析思路
  18. 阿里巴巴计算机招聘学历要求,阿里巴巴招程序员,到底看不看学历?
  19. EmberZNet EFR32 OTA 注意点
  20. cookie的domain属性

热门文章

  1. zynq linux如何使用pl ip,米联客FDMA IP在LINUX下实现PL和PS数据共享测试总结
  2. 缓存穿透、缓存雪崩、缓存击穿?
  3. linux 解压文件夹下所有zip文件
  4. java反射无法获取_Java反射'无法设置'错误
  5. ubuntu16.04 无线/Wifi 上网速度慢的解决方法
  6. 频繁项集挖掘实战和关联规则产生
  7. 数据库中索引的优缺点和分类
  8. 智能家电市场群雄割据 “内冷外热”的现实何时能改变?
  9. 轻量级网络之CondenseNet
  10. 对于香农采样定律的简短理解