Webview文件上传android冻结应用程序

时间:2016-03-16 08:20:59

标签: android file-upload webview android-webview

我正在制作一个需要上传文件的webview应用。我实现了包括文件选择器或选择用相机拍照的选项。打开文件选择器或选择摄像机时,应用程序会冻结并关闭。

我在网上看了很多,无法找到解决方案。有人可以帮我解决这个问题吗?代码示例如下:

public class MainActivity extends Activity {

private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static final String TAG = "MainActivity";

private BroadcastReceiver mRegistrationBroadcastReceiver;
private ProgressBar mRegistrationProgressBar;
public String regToken;


public class GeoWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}


public class GeoWebChromeClient extends WebChromeClient {
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
    }
}

public static final int INPUT_FILE_REQUEST_CODE = 1;
public static final String EXTRA_FROM_NOTIFICATION = "EXTRA_FROM_NOTIFICATION";

WebView mWebView;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE=1;

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        android.Manifest.permission.READ_EXTERNAL_STORAGE,
        android.Manifest.permission.WRITE_EXTERNAL_STORAGE
};

public static void verifyStoragePermissions(Activity activity) {

    int permission = ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

public MainActivity() {
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);



    mRegistrationBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            SharedPreferences sharedPreferences =
                    PreferenceManager.getDefaultSharedPreferences(context);
            boolean sentToken = sharedPreferences
                    .getBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false);

            Log.i(TAG, "++++++++++++++++++++++++++++++++++ REGID " + sharedPreferences
                    .getString(QuickstartPreferences.TOKEN_REGISTER, "registrationComplete"));
            regToken = sharedPreferences.getString(QuickstartPreferences.TOKEN_REGISTER, "registrationComplete");
            Log.i(TAG, "++++++++++++++++++++++++++++++++++ REGID " + regToken);

            mWebView = (WebView) findViewById(R.id.activity_main_webview);

            WebSettings webSettings = mWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);
            webSettings.setGeolocationEnabled(true);
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
            mWebView.setWebViewClient(new GeoWebViewClient());
            webSettings.setGeolocationEnabled(true);
            mWebView.setWebChromeClient(new GeoWebChromeClient());
            mWebView.setWebViewClient(new myWebClient());

            mWebView.setWebChromeClient(new WebChromeClient() {
                public boolean onShowFileChooser(
                        WebView webView, ValueCallback<Uri[]> filePathCallback,
                        WebChromeClient.FileChooserParams fileChooserParams) {
                    if (mFilePathCallback != null) {
                        mFilePathCallback.onReceiveValue(null);
                    }
                    mFilePathCallback = filePathCallback;

                    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                        File photoFile = null;
                        try {
                            photoFile = createImageFile();
                            takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
                        } catch (IOException ex) {
                            Log.e(TAG, "Unable to create Image File", ex);
                        }

                        if (photoFile != null) {
                            mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
                            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                                    Uri.fromFile(photoFile));
                        } else {
                            takePictureIntent = null;
                        }
                    }

                    Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
                    contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
                    contentSelectionIntent.setType("image/*");

                    Intent[] intentArray;
                    if (takePictureIntent != null) {
                        intentArray = new Intent[]{takePictureIntent};
                    } else {
                        intentArray = new Intent[0];
                    }

                    Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
                    chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
                    chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);

                    startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);

                    return true;
                }
            });

            Bundle extras = getIntent().getExtras();
            String urltje;

            if(extras != null && extras.getString("url") != null){
                urltje = extras.getString("url");
                Log.i(TAG, "++++++++++++++++++++++++++++++++++ URL " + urltje);
                mWebView.loadUrl(urltje);
            }else {
                mWebView.loadUrl("http://www.elevent.nl/?page=15&regID=" + regToken);
            }

            mWebView.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    view.loadUrl(url);
                    return false;
                }
            });
        }
    };

    if (checkPlayServices()) {
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }


}

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File imageFile = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );
    return imageFile;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setUpWebViewDefaults(WebView webView) {
    WebSettings settings = webView.getSettings();

    // Enable Javascript
    settings.setJavaScriptEnabled(true);

    // Use WideViewport and Zoom out if there is no viewport defined
    settings.setUseWideViewPort(true);
    settings.setLoadWithOverviewMode(true);

    // Enable pinch to zoom without the zoom buttons
    settings.setBuiltInZoomControls(true);

    if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
        // Hide the zoom controls for HONEYCOMB+
        settings.setDisplayZoomControls(false);
    }

    // Enable remote debugging via chrome://inspect
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        WebView.setWebContentsDebuggingEnabled(true);
    }

    // We set the WebViewClient to ensure links are consumed by the WebView rather
    // than passed to a browser if it can
    mWebView.setWebViewClient(new WebViewClient());
}

@Override
public void onActivityResult (int requestCode, int resultCode, Intent data) {
    if(requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
        super.onActivityResult(requestCode, resultCode, data);
        return;
    }

    Uri[] results = null;

    // Check that the response is a good one
    if(resultCode == Activity.RESULT_OK) {
        if(data == null || data.getData() == null) {
            // If there is not data, then we may have taken a photo
            if(mCameraPhotoPath != null) {
                results = new Uri[]{Uri.parse(mCameraPhotoPath)};
            }
        } else {
            String dataString = data.getDataString();
            if (dataString != null) {
                results = new Uri[]{Uri.parse(dataString)};
            }
        }
    }

    mFilePathCallback.onReceiveValue(results);
    mFilePathCallback = null;
    return;
}

public class myWebClient extends WebViewClient
{
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        // TODO Auto-generated method stub
        super.onPageStarted(view, url, favicon);
    }



    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // TODO Auto-generated method stub

        view.loadUrl(url);
        return true;

    }

    @Override
    public void onPageFinished(WebView view, String url) {
        // TODO Auto-generated method stub
        super.onPageFinished(view, url);
    }
}

@Override
public void onConfigurationChanged(Configuration newConfig){
    super.onConfigurationChanged(newConfig);
}

@Override
public void onBackPressed() {
    // Pop the browser back stack or exit the activity
    if (mWebView.canGoBack()) {
        mWebView.goBack();
    }
    else {
        super.onBackPressed();
    }
}

@Override
protected void onResume() {
    super.onResume();
    LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
            new IntentFilter(QuickstartPreferences.REGISTRATION_COMPLETE));
}

@Override
protected void onPause() {
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
    super.onPause();
}

/**
 * Check the device to make sure it has the Google Play Services APK. If
 * it doesn't, display a dialog that allows users to download the APK from
 * the Google Play Store or enable it in the device's system settings.
 */
private boolean checkPlayServices() {
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                    .show();
        } else {
            Log.i(TAG, "This device is not supported.");
            finish();
        }
        return false;
    }
    return true;
}

可能是一个重复的问题。但我是新手制作Android应用程序而我无法找到解决方案!

抱歉,我忘了包含logcat。这是我点击文件输入后获得的logcat。

03-16 08:29:35.485 3153-3153/webdesign.jk.elevent E/MainActivity: Unable to create Image File
  java.io.IOException: open failed: EACCES (Permission denied)
      at java.io.File.createNewFile(File.java:939)
      at java.io.File.createTempFile(File.java:1004)
      at webdesign.jk.elevent.MainActivity.createImageFile(MainActivity.java:214)
      at webdesign.jk.elevent.MainActivity.access$100(MainActivity.java:39)
      at webdesign.jk.elevent.MainActivity$1$1.onShowFileChooser(MainActivity.java:142)
      at com.android.webview.chromium.WebViewContentsClientAdapter.showFileChooser(WebViewContentsClientAdapter.java:1104)
      at org.chromium.android_webview.AwWebContentsDelegateAdapter.runFileChooser(AwWebContentsDelegateAdapter.java:219)
      at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
      at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:53)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:148)
      at android.app.ActivityThread.main(ActivityThread.java:5417)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
   Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
      at libcore.io.Posix.open(Native Method)
      at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
      at java.io.File.createNewFile(File.java:932)
      at java.io.File.createTempFile(File.java:1004) 
      at webdesign.jk.elevent.MainActivity.createImageFile(MainActivity.java:214) 
      at webdesign.jk.elevent.MainActivity.access$100(MainActivity.java:39) 
      at webdesign.jk.elevent.MainActivity$1$1.onShowFileChooser(MainActivity.java:142) 
      at com.android.webview.chromium.WebViewContentsClientAdapter.showFileChooser(WebViewContentsClientAdapter.java:1104) 
      at org.chromium.android_webview.AwWebContentsDelegateAdapter.runFileChooser(AwWebContentsDelegateAdapter.java:219) 
      at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) 
      at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:53) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:148) 
      at android.app.ActivityThread.main(ActivityThread.java:5417) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

下面我将包括我的清单文件。

<?xml version="1.0" encoding="utf-8"?>

<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.WAKE_LOCK" />


<!-- gcm permissions -->
<permission
    android:name="webdesign.jk.elevent.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="webdesign.jk.elevent.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-feature android:name="android.hardware.camera"
    android:required="true" />

1 个答案:

答案 0 :(得分:1)

createImageFile()方法中尝试将其更改为

File storageDir = this.getCacheDir();
File imageFile = File.createTempFile(
        imageFileName,  /* prefix */
        ".jpg",         /* suffix */
        storageDir      /* directory */
);

看看它是否有效。还要确保storageDir目录存在。

File storageDir = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);