android中webview控件实现拍照以及相册上传图片功能

在android中webview控件加载微网站时,有的时候需要通过html标签input file来上传图片,而android中webview不提供拍照以及相册上传图片功能。所以需要重新来写代码来实现通过input file 来上传图片。

开始实现input file来拍照以及相册上传图片功能。

第一步: 重载WebChromeClient类

this.appView.setWebChromeClient(new JCordovaChromeClient(this));

 第二步: 给重载类添加拍照以及相册方法

	// <input type="file" name="fileField" id="fileField" />
	// Android > 4.1.1
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg,
			String acceptType, String capture) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);
	}

	// 3.0 +
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);
	}

	// Android < 3.0
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);

	}

	private Intent createDefaultOpenableIntent() {
		Intent i = new Intent(Intent.ACTION_GET_CONTENT);
		i.addCategory(Intent.CATEGORY_OPENABLE);
		i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				"image/*");

		Intent chooser = createChooserIntent(createCameraIntent()/*
																 * ,
																 * createCamcorderIntent
																 * (),
																 * createSoundRecorderIntent
																 * ()
																 */);

		chooser.putExtra(Intent.EXTRA_INTENT, i);

		return chooser;

	}

	private Intent createChooserIntent(Intent... intents) {
		Intent chooser = new Intent(Intent.ACTION_CHOOSER);
		chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
		chooser.putExtra(Intent.EXTRA_TITLE, "选择图片");
		return chooser;
	}

	@SuppressWarnings("static-access")
	private Intent createCameraIntent() {
		Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		File externalDataDir = Environment
				.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
		File cameraDataDir = new File(externalDataDir.getAbsolutePath()
				+ File.separator + "515aaa");

		cameraDataDir.mkdirs();
		String mCameraFilePath = cameraDataDir.getAbsolutePath()
				+ File.separator + System.currentTimeMillis() + ".jpg";

		this.mCameraFilePath = mCameraFilePath;

		cameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);

		cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,
				Uri.fromFile(new File(mCameraFilePath)));

		return cameraIntent;

	}

	/*
	 * private Intent createCamcorderIntent() { return new
	 * Intent(MediaStore.ACTION_VIDEO_CAPTURE); }
	 * 
	 * private Intent createSoundRecorderIntent() { return new
	 * Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); }
	 */

在这里把最后两个方法已注释,因为我开发的app中不需要上传视频和上传音频。

完成之后我们还需要添加一个拍完照之后图片处理方法:

	public static Uri getImageContentUri(Context context, java.io.File imageFile) {
		String filePath = imageFile.getAbsolutePath();
		Cursor cursor = context.getContentResolver().query(
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				new String[] { MediaStore.Images.Media._ID },
				MediaStore.Images.Media.DATA + "=? ",
				new String[] { filePath }, null);
		if (cursor != null && cursor.moveToFirst()) {
			int id = cursor.getInt(cursor
					.getColumnIndex(MediaStore.MediaColumns._ID));
			Uri baseUri = Uri.parse("content://media/external/images/media");
			return Uri.withAppendedPath(baseUri, "" + id);
		} else {
			if (imageFile.exists()) {
				ContentValues values = new ContentValues();
				values.put(MediaStore.Images.Media.DATA, filePath);
				return context.getContentResolver().insert(
						MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
			} else {
				return null;
			}
		}
	}

整体代码如下:

package com.jhonse.aaa515;

import java.io.File;

import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.CordovaInterface;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.webkit.ValueCallback;
import android.webkit.WebView;

public class JCordovaChromeClient extends CordovaChromeClient {

	private aaa515 jaaa515;
	public static final int FILECHOOSER_RESULTCODE = 5173;
	public static String mCameraFilePath = "";

	@SuppressWarnings("deprecation")
	public JCordovaChromeClient(CordovaInterface cordova) {
		super(cordova);
		this.jaaa515 = (aaa515) cordova;
	}

	@Override
	public void onProgressChanged(WebView view, int newProgress) {
		super.onProgressChanged(view, newProgress);
	}

	// <input type="file" name="fileField" id="fileField" />
	// Android > 4.1.1
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg,
			String acceptType, String capture) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);
	}

	// 3.0 +
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);
	}

	// Android < 3.0
	@SuppressWarnings("static-access")
	public void openFileChooser(ValueCallback<Uri> uploadMsg) {
		super.mUploadMessage = uploadMsg;
		this.jaaa515.startActivityForResult(createDefaultOpenableIntent(),
				this.FILECHOOSER_RESULTCODE);

	}

	private Intent createDefaultOpenableIntent() {
		Intent i = new Intent(Intent.ACTION_GET_CONTENT);
		i.addCategory(Intent.CATEGORY_OPENABLE);
		i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				"image/*");

		Intent chooser = createChooserIntent(createCameraIntent()/*
																 * ,
																 * createCamcorderIntent
																 * (),
																 * createSoundRecorderIntent
																 * ()
																 */);

		chooser.putExtra(Intent.EXTRA_INTENT, i);

		return chooser;

	}

	private Intent createChooserIntent(Intent... intents) {
		Intent chooser = new Intent(Intent.ACTION_CHOOSER);
		chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
		chooser.putExtra(Intent.EXTRA_TITLE, "选择图片");
		return chooser;
	}

	@SuppressWarnings("static-access")
	private Intent createCameraIntent() {
		Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		File externalDataDir = Environment
				.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
		File cameraDataDir = new File(externalDataDir.getAbsolutePath()
				+ File.separator + "515aaa");

		cameraDataDir.mkdirs();
		String mCameraFilePath = cameraDataDir.getAbsolutePath()
				+ File.separator + System.currentTimeMillis() + ".jpg";

		this.mCameraFilePath = mCameraFilePath;

		cameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);

		cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,
				Uri.fromFile(new File(mCameraFilePath)));

		return cameraIntent;

	}

	/*
	 * private Intent createCamcorderIntent() { return new
	 * Intent(MediaStore.ACTION_VIDEO_CAPTURE); }
	 * 
	 * private Intent createSoundRecorderIntent() { return new
	 * Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); }
	 */

	public static Uri getImageContentUri(Context context, java.io.File imageFile) {
		String filePath = imageFile.getAbsolutePath();
		Cursor cursor = context.getContentResolver().query(
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				new String[] { MediaStore.Images.Media._ID },
				MediaStore.Images.Media.DATA + "=? ",
				new String[] { filePath }, null);
		if (cursor != null && cursor.moveToFirst()) {
			int id = cursor.getInt(cursor
					.getColumnIndex(MediaStore.MediaColumns._ID));
			Uri baseUri = Uri.parse("content://media/external/images/media");
			return Uri.withAppendedPath(baseUri, "" + id);
		} else {
			if (imageFile.exists()) {
				ContentValues values = new ContentValues();
				values.put(MediaStore.Images.Media.DATA, filePath);
				return context.getContentResolver().insert(
						MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
			} else {
				return null;
			}
		}
	}
}

 第三步: 重载Activity的startActivityForResult方法和onActivityResult方法。

我们需要对拍照以及相册返回的数据进行处理。

public void startActivityForResult(CordovaPlugin command, Intent intent,
			int requestCode) {
		this.activityResultCallback = command;
		this.activityResultKeepRunning = this.keepRunning;

		// If multitasking turned on, then disable it for activities that return
		// results
		if (command != null) {
			this.keepRunning = false;
		}
		// Start activity
		super.startActivityForResult(intent, requestCode);
	}

	@SuppressLint("NewApi")
	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {
		if (appView != null
				&& requestCode == JCordovaChromeClient.FILECHOOSER_RESULTCODE) {

			ValueCallback<Uri> mUploadMessage = this.appView
					.getWebChromeClient().getValueCallback();
			if (null == mUploadMessage) {
				return;
			}
			Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
					: intent.getData();

			if (intent == null && JCordovaChromeClient.mCameraFilePath != "") {
				result = JCordovaChromeClient.getImageContentUri(this,
						new File(JCordovaChromeClient.mCameraFilePath));
			}

			mUploadMessage.onReceiveValue(result);
			mUploadMessage = null;
		}
		super.onActivityResult(requestCode, resultCode, intent);
	}

 第四步: 调用流程分析

1.  首先通过重载CordovaChromeClient类中的方法:openFileChooser,来匹配input file 打开文件上传功能。

2.  通过这个openFileChooser方法,我们可以添加拍照、相册、视频、音频。

3.  当拍照或者选择相册图片之后,就会调用Activity中的startActivityForResult方法。并且是通过自定义的FILECHOOSER_RESULTCODE来标识拍照、相册。

4.  startActivityForResult把对应的拍照、相册图片数据返回给onActivityResult方法来处理。

5.  onActivityResult方法中,如果是相册选择图片的话,就会返回图片数据,而如果是拍照的话,不会返回数据。所以我们需要对拍照的图片进行处理。

6. 所以通过自定义的getImageContentUri方法来处理拍完照之后的图片。

7. 说明: 因为拍照的图片,是通过自定义图片路径来生成的,所以对应的图片路径以及图片名称都是知道的。

Author: jhonse

Jhonse技术博客: http://blog.jhonse.com

One thought on “android中webview控件实现拍照以及相册上传图片功能”

Leave a Reply

Your email address will not be published. Required fields are marked *