原生+H5开发之:Android webview配置

在上一篇文章Android 原生开发、H5、React-Native开发特点,我们可以了解到三种Android开发方式的区别和优缺点。[Android开发:原生+H5]系列的文章,将主要讲解Android原生+H5开发相关,这一节主要是Android原生+H5开发时要使用WebView,要使WebView正确的显示加载H5页面和功能需要做相关的配置。

AndroidManifest权限添加

  请一定、务必在AndroidManifest中添加如下权限,否则是无法正常打开显示H5页面的。 
  这个一定要单独拿出来强调一下,以防你其他代码啊,配置啊什么的都写好了,但就是不显示,然后你就各种找问题,发愁,恼怒,耽误时间。因为楼主就曾经犯过这样的错误,真的被自己粗心蠢哭,哭哭哭……

1 <uses-permission android:name="android.permission.INTERNET"/>

WebView使用步骤

1. 添加AndroidManifest权限。

1 <uses-permission android:name="android.permission.INTERNET"/>

2. 布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     tools:context="com.app.www.webapp.SecondActivity">
 9 
10     <WebView
11         android:id="@+id/webView"
12         android:layout_width="match_parent"
13         android:layout_height="match_parent" />
14 
15 </LinearLayout>

3. 获取WebView对象。

1 webView = this.findViewById(R.id.webView);

4. WebSettings配置WebView。下面有具体的配置说明。 
5. 设置加载地址。

1 webView.loadUrl(url);

  到这一步为止,WebView就可以正常的显示了,如果我们想要对WebView做进一步的监听处理,就需要下面的设置。 
   
6. 设置WebViewClient。 WebViewClient主要是监听WebView加载进程,平常我们对webview加载的处理,例如加一些进度条、跳转设置之类的都是通过WebViewClient类完成。在下面我们会讲到。 
7. 设置WebChromeClient。 有时候我们不想原生去调用手机的拍照和相册,如果我们想要用H5去掉用的话,我们需要去重新WebChromeClient类,并进行设置,这样H5才能成功的调用拍照和相册。下面会细讲。

WebSettings类配置

 1         /**支持Js**/
 2         setting.setJavaScriptEnabled(true);
 3 
 4         /**设置自适应屏幕,两者合用**/
 5         //将图片调整到适合webview的大小
 6         setting.setUseWideViewPort(true);
 7         // 缩放至屏幕的大小
 8         setting.setLoadWithOverviewMode(true);
 9 
10         /**缩放操作**/
11         // 是否支持画面缩放,默认不支持
12         setting.setBuiltInZoomControls(true);
13         setting.setSupportZoom(true);
14         // 是否显示缩放图标,默认显示
15         setting.setDisplayZoomControls(false);
16         // 设置网页内容自适应屏幕大小
17         setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
18 
19         /**设置允许JS弹窗**/
20         setting.setJavaScriptCanOpenWindowsAutomatically(true);
21         setting.setDomStorageEnabled(true);
22 
23         /**关闭webview中缓存**/
24         setting.setCacheMode(WebSettings.LOAD_NO_CACHE);
25         /**设置可以访问文件 **/
26         setting.setAllowFileAccess(true);
27         setting.setAllowFileAccessFromFileURLs(true);
28         setting.setAllowUniversalAccessFromFileURLs(true);

WebViewClient类

  如果不进行设置WebViewClient的话,我们的WebView通常会跳转到手机自带的浏览器去进行显示,但是我们想要的是在app内显示,所以我们需要对WebViewClient进行设置。对这个类的使用我们之前在 Android 网络连接——WebView这篇文章中也讲过,这里我就只复制一下。

WebView加载失败设置

  我们在使用浏览器时,我们经常会看到,如果页面加载失败会出现一个提示的页面。我们自己的浏览器当然也少不了这个功能。设置加载页面失败调用WebView的setWebViewClient()方法,传入匿名WebViewClient对象,重写onReceivedError()方法,在该方法内进行处理。

1 webView.setWebViewClient(new WebViewClient() {
2     /*
3     网络连接错误时调用
4     */
5     @Override
6     public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
7         super.onReceivedError(view, errorCode, description, failingUrl);
8     }
9 });

WebView网页加载进度条显示

 1         webView.setWebChromeClient(new WebChromeClient() {
 2             @Override
 3             public void onProgressChanged(WebView view, int newProgress) {
 4                 super.onProgressChanged(view, newProgress);
 5                 progressBar.setProgress(newProgress);//网络加载时设置进度条进度
 6             }
 7         });
 8         webView.setWebViewClient(new WebViewClient() {
 9             /*
10             网络开始加载时调用
11             */
12             @Override
13             public void onPageStarted(WebView view, String url, Bitmap favicon) {
14                 super.onPageStarted(view, url, favicon);
15                 progressBar.setVisibility(View.VISIBLE);//设置显示进度条
16             }
17 
18             /*
19             网络加载结束时调用
20             */
21             @Override
22             public void onPageFinished(WebView view, String url) {
23                 super.onPageFinished(view, url);
24                 progressBar.setVisibility(View.GONE);//设置去除进度条
25             }
26         });

WebChromeClient类

  H5想要调用我们手机的相册和拍照,直接调用是不行的,我们必须在WebView设置中进行设置。重写WebChromeClient类。

  1 import android.annotation.SuppressLint;
  2 import android.annotation.TargetApi;
  3 import android.app.Activity;
  4 import android.content.ClipData;
  5 import android.content.ComponentName;
  6 import android.content.ContentUris;
  7 import android.content.Context;
  8 import android.content.Intent;
  9 import android.content.pm.PackageManager;
 10 import android.content.pm.ResolveInfo;
 11 import android.database.Cursor;
 12 import android.graphics.Bitmap;
 13 import android.net.Uri;
 14 import android.os.Build;
 15 import android.os.Environment;
 16 import android.os.Parcelable;
 17 import android.provider.DocumentsContract;
 18 import android.provider.MediaStore;
 19 import android.support.v7.app.AppCompatActivity;
 20 import android.os.Bundle;
 21 import android.view.KeyEvent;
 22 import android.webkit.ValueCallback;
 23 import android.webkit.WebChromeClient;
 24 import android.webkit.WebSettings;
 25 import android.webkit.WebView;
 26 import android.webkit.WebViewClient;
 27 import android.widget.Toast;
 28 
 29 import java.io.File;
 30 import java.util.ArrayList;
 31 import java.util.List;
 32 
 33 import static android.view.KeyEvent.KEYCODE_BACK;
 34 
 35 public class SecondActivity extends Activity {
 36     private WebView webView;
 37     private Intent intent;
 38     private String url;
 39     /**
 40      * 表单的数据信息
 41      */
 42     private ValueCallback<Uri> mUploadMessage;
 43     private ValueCallback<Uri[]> mUploadCallbackAboveL;
 44     /**
 45      * 表单的结果回调</span>
 46      */
 47     private final static int FILECHOOSER_RESULTCODE = 1;
 48     private Uri imageUri;
 49     @Override
 50     protected void onCreate(Bundle savedInstanceState) {
 51         super.onCreate(savedInstanceState);
 52         setContentView(R.layout.activity_second);
 53         intent = getIntent();
 54         url = intent.getStringExtra("url");
 55         Toast.makeText(this, url, Toast.LENGTH_SHORT).show();
 56         webView = this.findViewById(R.id.webView);
 57 
 58         initWebView();
 59 //        this.webView.loadUrl("http://192.168.1.105:8099/photo");
 60         webView.loadUrl(url);
 61 
 62         webView.setWebViewClient(new WebViewClient() {
 63             @Override
 64             public boolean shouldOverrideUrlLoading(WebView view, String url) {
 65                 return super.shouldOverrideUrlLoading(view, url);
 66             }
 67 
 68             @Override
 69             public void onPageStarted(WebView view, String url, Bitmap favicon) {
 70                 super.onPageStarted(view, url, favicon);
 71             }
 72 
 73             @Override
 74             public void onPageFinished(WebView view, String url) {
 75                 super.onPageFinished(view, url);
 76             }
 77         });
 78         webView.setWebChromeClient(new OpenFileChromeClient());
 79     }
 80 
 81     public class OpenFileChromeClient extends WebChromeClient {
 82 
 83         @Override
 84         public boolean onShowFileChooser(WebView webView,
 85                                          ValueCallback<Uri[]> filePathCallback,
 86                                          FileChooserParams fileChooserParams) {
 87             mUploadCallbackAboveL = filePathCallback;
 88             take();
 89             return true;
 90         }
 91 
 92         /**
 93          * Android < 3.0 调用这个方法
 94          *
 95          * @param uploadMsg
 96          */
 97         public void openFileChooser(ValueCallback<Uri> uploadMsg) {
 98             mUploadMessage = uploadMsg;
 99             take();
100         }
101 
102         /**
103          * Android < 3.0 调用这个方法
104          *
105          * @param uploadMsg
106          * @param acceptType
107          */
108         public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
109             mUploadMessage = uploadMsg;
110             take();
111         }
112 
113         /**
114          * Android > 4.1.1 调用这个方法
115          *
116          * @param uploadMsg
117          * @param acceptType
118          * @param capture
119          */
120         public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
121             mUploadMessage = uploadMsg;
122             take();
123         }
124     }
125 
126 
127     private void initWebView() {
128         WebSettings setting = webView.getSettings();
129         /**支持Js**/
130         setting.setJavaScriptEnabled(true);
131 
132         /**设置自适应屏幕,两者合用**/
133         //将图片调整到适合webview的大小
134         setting.setUseWideViewPort(true);
135         // 缩放至屏幕的大小
136         setting.setLoadWithOverviewMode(true);
137 
138         /**缩放操作**/
139         // 是否支持画面缩放,默认不支持
140         setting.setBuiltInZoomControls(true);
141         setting.setSupportZoom(true);
142         // 是否显示缩放图标,默认显示
143         setting.setDisplayZoomControls(false);
144         // 设置网页内容自适应屏幕大小
145         setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
146 
147         /**设置允许JS弹窗**/
148         setting.setJavaScriptCanOpenWindowsAutomatically(true);
149         setting.setDomStorageEnabled(true);
150 
151 
152         /**关闭webview中缓存**/
153         setting.setCacheMode(WebSettings.LOAD_NO_CACHE);
154         /**设置可以访问文件 **/
155         setting.setAllowFileAccess(true);
156         setting.setAllowFileAccessFromFileURLs(true);
157         setting.setAllowUniversalAccessFromFileURLs(true);
158 
159     }
160 
161 
162     @Override
163     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
164         super.onActivityResult(requestCode, resultCode, data);
165         if (requestCode == FILECHOOSER_RESULTCODE) {
166             if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
167             Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
168             if (mUploadCallbackAboveL != null) {
169                 onActivityResultAboveL(requestCode, resultCode, data);
170             } else if (mUploadMessage != null) {
171 
172                 if (result != null) {
173                     String path = getPath(getApplicationContext(),
174                             result);
175                     Uri uri = Uri.fromFile(new File(path));
176                     mUploadMessage
177                             .onReceiveValue(uri);
178                 } else {
179                     mUploadMessage.onReceiveValue(imageUri);
180                 }
181                 mUploadMessage = null;
182 
183 
184             }
185         }
186     }
187 
188     @Override
189     public boolean onKeyDown(int keyCode, KeyEvent event) {
190         if ((keyCode == KEYCODE_BACK) && webView.canGoBack()) {
191             webView.goBack();
192             return true;
193         }
194         return super.onKeyDown(keyCode, event);
195     }
196 
197     @SuppressWarnings("null")
198     @TargetApi(Build.VERSION_CODES.BASE)
199     private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
200         if (requestCode != FILECHOOSER_RESULTCODE
201                 || mUploadCallbackAboveL == null) {
202             return;
203         }
204 
205         Uri[] results = null;
206 
207         if (resultCode == Activity.RESULT_OK) {
208 
209             if (data == null) {
210 
211                 results = new Uri[]{imageUri};
212             } else {
213                 String dataString = data.getDataString();
214                 ClipData clipData = data.getClipData();
215 
216                 if (clipData != null) {
217                     results = new Uri[clipData.getItemCount()];
218                     for (int i = 0; i < clipData.getItemCount(); i++) {
219                         ClipData.Item item = clipData.getItemAt(i);
220                         results[i] = item.getUri();
221                     }
222                 }
223 
224                 if (dataString != null)
225                     results = new Uri[]{Uri.parse(dataString)};
226             }
227         }
228         if (results != null) {
229             mUploadCallbackAboveL.onReceiveValue(results);
230             mUploadCallbackAboveL = null;
231         } else {
232             results = new Uri[]{imageUri};
233             mUploadCallbackAboveL.onReceiveValue(results);
234             mUploadCallbackAboveL = null;
235         }
236 
237         return;
238     }
239 
240 
241     private void take() {
242         File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
243         // Create the storage directory if it does not exist
244         if (!imageStorageDir.exists()) {
245             imageStorageDir.mkdirs();
246         }
247         File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
248         imageUri = Uri.fromFile(file);
249 
250         final List<Intent> cameraIntents = new ArrayList<Intent>();
251         final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
252         final PackageManager packageManager = getPackageManager();
253         final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
254         for (ResolveInfo res : listCam) {
255             final String packageName = res.activityInfo.packageName;
256             final Intent i = new Intent(captureIntent);
257             i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
258             i.setPackage(packageName);
259             i.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
260             cameraIntents.add(i);
261 
262         }
263         Intent i = new Intent(Intent.ACTION_GET_CONTENT);
264         i.addCategory(Intent.CATEGORY_OPENABLE);
265         i.setType("image/*");
266         Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
267         chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
268         SecondActivity.this.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
269     }
270 
271     @SuppressLint("NewApi")
272     @TargetApi(Build.VERSION_CODES.KITKAT)
273     public static String getPath(final Context context, final Uri uri) {
274         final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
275 
276         // DocumentProvider
277         if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
278             // ExternalStorageProvider
279             if (isExternalStorageDocument(uri)) {
280                 final String docId = DocumentsContract.getDocumentId(uri);
281                 final String[] split = docId.split(":");
282                 final String type = split[0];
283 
284                 if ("primary".equalsIgnoreCase(type)) {
285                     return Environment.getExternalStorageDirectory() + "/" + split[1];
286                 }
287 
288                 // TODO handle non-primary volumes
289             }
290             // DownloadsProvider
291             else if (isDownloadsDocument(uri)) {
292 
293                 final String id = DocumentsContract.getDocumentId(uri);
294                 final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
295 
296                 return getDataColumn(context, contentUri, null, null);
297             }
298             // MediaProvider
299             else if (isMediaDocument(uri)) {
300                 final String docId = DocumentsContract.getDocumentId(uri);
301                 final String[] split = docId.split(":");
302                 final String type = split[0];
303 
304                 Uri contentUri = null;
305                 if ("image".equals(type)) {
306                     contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
307                 } else if ("video".equals(type)) {
308                     contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
309                 } else if ("audio".equals(type)) {
310                     contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
311                 }
312 
313                 final String selection = "_id=?";
314                 final String[] selectionArgs = new String[]{split[1]};
315 
316                 return getDataColumn(context, contentUri, selection, selectionArgs);
317             }
318         }
319         // MediaStore (and general)
320         else if ("content".equalsIgnoreCase(uri.getScheme())) {
321             return getDataColumn(context, uri, null, null);
322         }
323         // File
324         else if ("file".equalsIgnoreCase(uri.getScheme())) {
325             return uri.getPath();
326         }
327 
328         return null;
329     }
330 
331 
332     /**
333      * Get the value of the data column for this Uri. This is useful for
334      * MediaStore Uris, and other file-based ContentProviders.
335      *
336      * @param context       The context.
337      * @param uri           The Uri to query.
338      * @param selection     (Optional) Filter used in the query.
339      * @param selectionArgs (Optional) Selection arguments used in the query.
340      * @return The value of the _data column, which is typically a file path.
341      */
342     public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
343         Cursor cursor = null;
344         final String column = "_data";
345         final String[] projection = {column};
346 
347         try {
348             cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
349             if (cursor != null && cursor.moveToFirst()) {
350                 final int column_index = cursor.getColumnIndexOrThrow(column);
351                 return cursor.getString(column_index);
352             }
353         } finally {
354             if (cursor != null) cursor.close();
355         }
356         return null;
357     }
358 
359 
360     /**
361      * @param uri The Uri to check.
362      * @return Whether the Uri authority is ExternalStorageProvider.
363      */
364     public static boolean isExternalStorageDocument(Uri uri) {
365         return "com.android.externalstorage.documents".equals(uri.getAuthority());
366     }
367 
368 
369     /**
370      * @param uri The Uri to check.
371      * @return Whether the Uri authority is DownloadsProvider.
372      */
373     public static boolean isDownloadsDocument(Uri uri) {
374         return "com.android.providers.downloads.documents".equals(uri.getAuthority());
375     }
376 
377 
378     /**
379      * @param uri The Uri to check.
380      * @return Whether the Uri authority is MediaProvider.
381      */
382     public static boolean isMediaDocument(Uri uri) {
383         return "com.android.providers.media.documents".equals(uri.getAuthority());
384     }
385 }

完整代码下载地址:下载地址

转载于:https://www.cnblogs.com/univalsoft-mobile-team/p/8807938.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值