2012-07-30 72 views
28

我正在開發一個Android應用程序。基本上它是一個WebView和一個progressBar。 Facebook的移動網站(m.facebook.com)載入WebViewAndroid WebView文件上傳

當我點擊選擇文件按鈕來上傳圖片時,沒有任何反應。我嘗試了所有的解決方案,但都沒有工作。我正在運行4.0.3的Galaxy Note(GT-N7000)進行測試。我最小的SDK版本爲8

My App

這裏是我的詳細信息代碼...

public class IStyla extends Activity { 
    private ValueCallback<Uri> mUploadMessage; 
    private final static int FILECHOOSER_RESULTCODE = 1; 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 
     if (requestCode == FILECHOOSER_RESULTCODE) { 
      if (null == mUploadMessage) 
       return; 
      Uri result = intent == null || resultCode != RESULT_OK ? null 
        : intent.getData(); 
      mUploadMessage.onReceiveValue(result); 
      mUploadMessage = null; 

     } 
    } 
    private class MyWebChromeClient extends WebChromeClient { 
     public void openFileChooser(ValueCallback<Uri> uploadMsg) { 
      mUploadMessage = uploadMsg; 
      Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
      i.addCategory(Intent.CATEGORY_OPENABLE); 
      i.setType("image/*"); 
      IStyla.this.startActivityForResult(Intent.createChooser(i, "Image Browser"), FILECHOOSER_RESULTCODE); 
     } 

     @Override 
     public boolean onJsAlert(WebView view, String url, String message,final JsResult result) { 
      //handle Alert event, here we are showing AlertDialog 
      new AlertDialog.Builder(IStyla.this) 
       .setTitle("JavaScript Alert !") 
       .setMessage(message) 
       .setPositiveButton(android.R.string.ok, 
        new AlertDialog.OnClickListener() { 
         public void onClick(DialogInterface dialog, int which) { 
          // do your stuff 
          result.confirm(); 
         } 
        }).setCancelable(false).create().show(); 
      return true; 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_istyla); 
     WebView webView = (WebView) findViewById(R.id.webView1); 
     WebSettings webSettings = webView.getSettings(); 
     webSettings.setJavaScriptEnabled(true); 
     webView.setWebChromeClient(new MyWebChromeClient(){ 
      public void onProgressChanged(WebView view, int progress) { 
       // Activities and WebViews measure progress with different scales. 
       // The progress meter will automatically disappear when we reach 100% 
       ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar1); 
       if(progress < 100 && progressBar.getVisibility() == ProgressBar.GONE){ 
        progressBar.setVisibility(ProgressBar.VISIBLE); 
       } 
       progressBar.setProgress(progress); 
       if(progress == 100) { 
        progressBar.setVisibility(ProgressBar.GONE); 
       } 
      } 
      public void openFileChooser(ValueCallback<Uri> uploadMsg) { 
       mUploadMessage = uploadMsg; 
       Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
       i.addCategory(Intent.CATEGORY_OPENABLE); 
       i.setType("image/*"); 
       IStyla.this.startActivityForResult(Intent.createChooser(i, "Image Browser"), FILECHOOSER_RESULTCODE); 
      } 
     }); 
     webView.setWebViewClient(new WebViewClient() { 
      @Override 
      public boolean shouldOverrideUrlLoading(WebView view, String url) { 
       view.loadUrl(url); 
       ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar1); 
       progressBar.setVisibility(ProgressBar.VISIBLE); 
       return true; 
      } 

     }); 
     webView.loadUrl("https://m.facebook.com"); 

    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if (keyCode == KeyEvent.KEYCODE_BACK){ 
      if(((WebView)findViewById(R.id.webView1)).canGoBack()){ 
       ((WebView)findViewById(R.id.webView1)).goBack(); 
       return true; 
      } 
     } 
     return super.onKeyDown(keyCode, event); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.activity_istyla, menu); 
     return true; 
    } 

} 

感謝

+0

也許你需要權限,像[READ_EXTERNAL_STORAGE](http://developer.android.com/reference/android/Manifest.permission.html#READ_EXTERNAL_STORAGE) – neworld 2012-07-30 15:11:20

+0

我已經添加了權限,但它仍然不起作用。我已經在上面添加了我的代碼。 – 2012-07-30 15:22:39

+2

看看http://stackoverflow.com/questions/5907369/file-upload-in-webview – 2012-07-30 21:52:56

回答

4

鑑於高票數我猜測沒有人注意到第3條評論(來自David Esteves)包含a link with to answer to this question.

Michel Olivier說:

此解決方案也適用於蜂窩和冰淇淋三明治。似乎 像谷歌推出了一個很酷的新功能(接受屬性)和 忘記實現向後兼容的過載。

所以,你只需要一個openFileChooser超載添加到您的MyWebChromeClient類接受字符串參數,然後調用一個不:

public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) 
{ 
    this.openFileChooser(uploadMsg); 
} 

這樣做我是能夠使你的代碼運行如預期。

3

當調用WebChromeClient.OpenFileChooser中的AlertDialog時,您需要通知webchrome在返回按鈕的情況下未做任何選擇。 由於後退按鈕可以在您的對話框中按下,您必須處理對話框的OnCancel並告訴WebChrome選擇已完成。

如:

private ValueCallback<Uri> mUploadMessage; 
private final static int FILECHOOSER_RESULTCODE = 1; 
private final static int CAMERA_RESULTCODE = 2; 

... 

    webView.setWebChromeClient(new WebChromeClient() { 
     public boolean onConsoleMessage(ConsoleMessage cm) { 
     Log.d("MyApplication", cm.message() + " -- From line " 
          + cm.lineNumber() + " of " 
          + cm.sourceId()); 
     return true; 
     } 

     public void onExceededDatabaseQuota(String url, String 
      databaseIdentifier, long currentQuota, long estimatedSize, long 
      totalUsedQuota, QuotaUpdater quotaUpdater) { 
          quotaUpdater.updateQuota(estimatedSize+65536); 
      } 

    @SuppressWarnings("unused") 
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType, String capture) { 
      this.openFileChooser(uploadMsg); 
     } 

    @SuppressWarnings("unused") 
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String AcceptType) { 
     this.openFileChooser(uploadMsg); 
    } 

    public void openFileChooser(ValueCallback<Uri> uploadMsg) { 

     mUploadMessage = uploadMsg; 
     PesScreen.this.openImageIntent(); 
    } 
    });   

...

private void openImageIntent() { 

final File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); //file storage 


    root.mkdirs(); 
    int nCnt = 1; 
    if (root.listFiles() != null) 
     nCnt = root.listFiles().length; 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); 
    final String fname = String.format("/dest-%s-%d.jpg", sdf.format(Calendar.getInstance().getTime()), nCnt); 

    final File sdImageMainDirectory = new File(root.getAbsolutePath() + fname); 
    outputFileUri = Uri.fromFile(sdImageMainDirectory); 
//selection Photo/Gallery dialog 
    AlertDialog.Builder alert = new AlertDialog.Builder(this); 

    alert.setTitle("Select source"); 

    final CharSequence[] items = {"Photo", "Gallery"}; 
    alert.setItems(items, new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int whichButton) { 

      dialog.dismiss(); 
      if(whichButton == 0) 
      { 
       Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
       chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); 
       startActivityForResult(chooserIntent, CAMERA_RESULTCODE); 
      } 
      if(whichButton == 1) 
      { 
       Intent chooserIntent = new Intent(Intent.ACTION_GET_CONTENT); 
       chooserIntent.setType("image/*"); 
       startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE); 
      } 
     } 
    }); 
    alert.setOnCancelListener(new DialogInterface.OnCancelListener() { 
     @Override 
     public void onCancel(DialogInterface dialog) { 

     //here we have to handle BACK button/cancel 
      if (mUploadMessage!= null){ 
       mUploadMessage.onReceiveValue(null); 
      } 
      mUploadMessage = null; 
      dialog.dismiss(); 
     } 
    }); 
    alert.create().show(); 
5

Mike Olivier's reference通過Fr33dan共享是非常重要的。我在與你相似的情況下分享了對我有用的東西。

wv.setWebChromeClient(new WebChromeClient() { 

// For Android 3.0+ 
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { 
mUploadMessage = uploadMsg; 
Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
i.addCategory(Intent.CATEGORY_OPENABLE); 
i.setType("image/*"); 
MainActivity.this.startActivityForResult(Intent.createChooser(i, getString(R.string.fileselect)), MainActivity.FILECHOOSER_RESULTCODE); 
} 

// For Android < 3.0 
public void openFileChooser(ValueCallback<Uri> uploadMsg) { 
openFileChooser(uploadMsg, ""); 
} 


// For Android > 4.1 
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){ 
openFileChooser(uploadMsg, ""); 
} 
}); 

注:我發現這個地方在堆棧溢出和m0s' blog

此外,忽略lint警告。對於API 8及更高版本,此工具非常適用。

+0

thx關於android版本的重要部分 – BigTarakan 2013-07-13 13:35:27

+0

許多用戶仍在使用android 3.0及更低版本。甚至,我在SO社區發現了這一點。 :) – Chirag 2013-07-13 15:36:21

+0

甚至當我實現此功能時,什麼也沒有發生。而不是遞歸函數調用? – Sagar 2016-12-05 06:57:41

4

此代碼已經過100%測試,我在應用程序中使用它。做工精細

private class MyWebChromeClient extends WebChromeClient { 
    //The undocumented magic method override 
    //Eclipse will swear at you if you try to put @Override here 


    // For Android 3.0+ 
    public void openFileChooser(ValueCallback uploadMsg, String acceptType) { 
     mUploadMessage = uploadMsg; 
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
     intent.addCategory(Intent.CATEGORY_OPENABLE); 
     intent.setType("*/*"); 
     startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE); 
    } 

    //For Android 4.1+ only 
    protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { 
     mUploadMessage = uploadMsg; 
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
     intent.addCategory(Intent.CATEGORY_OPENABLE); 
     intent.setType("*/*"); 
     startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE); 
    } 

    protected void openFileChooser(ValueCallback<Uri> uploadMsg) { 
     mUploadMessage = uploadMsg; 
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
     intent.addCategory(Intent.CATEGORY_OPENABLE); 
     intent.setType("*/*"); 
     startActivityForResult(Intent.createChooser(intent, "File Chooser"), FILECHOOSER_RESULTCODE); 
    } 

    // For Lollipop 5.0+ Devices 
    public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { 
     if (uploadMessage != null) { 
      uploadMessage.onReceiveValue(null); 
      uploadMessage = null; 
     } 

     uploadMessage = filePathCallback; 
     Intent intent = null; 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      intent = fileChooserParams.createIntent(); 
     } 
     try { 
      startActivityForResult(intent, REQUEST_SELECT_FILE); 
     } catch (ActivityNotFoundException e) { 
      uploadMessage = null; 
      Toast.makeText(getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show(); 
      return false; 
     } 
     return true; 
    } 
+1

對我來說很好。但是當我從棉花糖設備中的文檔選擇器中選擇圖庫時,它沒有得到文件。 – 2016-07-21 09:46:28

+0

uploadMessage是什麼?什麼是REQUEST_SELECT_FILE? – asdjfiasd 2018-01-12 17:37:40

+0

uploadMessage是ValueCallback (檢查問題代碼)並且REQUEST_SELECT_FILE是用於onActivityResult()的任何整數。 – 2018-01-15 09:36:45

1

這個代碼將有助於解決這一問題

只需更新MainActivity。Java的文件與婁代碼

public class MainActivity extends Activity{ 
    private WebView mWebview ; 
    private ValueCallback<Uri> mUploadMessage; 
    public ValueCallback<Uri[]> uploadMessage; 
    public static final int REQUEST_SELECT_FILE = 100; 
    private final static int FILECHOOSER_RESULTCODE = 1; 

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

     mWebview = (WebView) findViewById(R.id.help_webview); 
     WebSettings webSettings = mWebview.getSettings(); 
     webSettings.setJavaScriptEnabled(true); 
     webSettings.setUseWideViewPort(true); 
     webSettings.setLoadWithOverviewMode(true); 
     webSettings.setAllowFileAccess(true); 
     webSettings.setJavaScriptCanOpenWindowsAutomatically(true); 
     webSettings.setBuiltInZoomControls(true); 
     webSettings.setPluginState(WebSettings.PluginState.ON); 
     webSettings.setSupportZoom(true); 
     webSettings.setAllowContentAccess(true); 



     final Activity activity = this; 
     mWebview.setWebViewClient(new WebViewClient() { 
      public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { 
       Toast.makeText(activity, description, Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     mWebview .loadUrl("http://www.google.com"); 

     String permission = Manifest.permission.CAMERA; 
     int grant = ContextCompat.checkSelfPermission(this, permission); 
     if (grant != PackageManager.PERMISSION_GRANTED) { 
      String[] permission_list = new String[1]; 
      permission_list[0] = permission; 
      ActivityCompat.requestPermissions(this, permission_list, 1); 
     } 


     mWebview.setWebChromeClient(new WebChromeClient() 
     { 
      // For 3.0+ Devices (Start) 
      // onActivityResult attached before constructor 
      protected void openFileChooser(ValueCallback uploadMsg, String acceptType) 
      { 
       mUploadMessage = uploadMsg; 
       Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
       i.addCategory(Intent.CATEGORY_OPENABLE); 
       i.setType("image/*"); 
       startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE); 
      } 


      // For Lollipop 5.0+ Devices 
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
      public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) 
      { 
       if (uploadMessage != null) { 
        uploadMessage.onReceiveValue(null); 
        uploadMessage = null; 
       } 

       uploadMessage = filePathCallback; 

       Intent intent = fileChooserParams.createIntent(); 
       try 
       { 
        startActivityForResult(intent, REQUEST_SELECT_FILE); 
       } catch (ActivityNotFoundException e) 
       { 
        uploadMessage = null; 
        Toast.makeText(MainActivity.this.getApplicationContext(), "Cannot Open File Chooser", Toast.LENGTH_LONG).show(); 
        return false; 
       } 
       return true; 
      } 

      //For Android 4.1 only 
      protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) 
      { 
       mUploadMessage = uploadMsg; 
       Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
       intent.addCategory(Intent.CATEGORY_OPENABLE); 
       intent.setType("image/*"); 
       startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE); 
      } 

      protected void openFileChooser(ValueCallback<Uri> uploadMsg) 
      { 
       mUploadMessage = uploadMsg; 
       Intent i = new Intent(Intent.ACTION_GET_CONTENT); 
       i.addCategory(Intent.CATEGORY_OPENABLE); 
       i.setType("image/*"); 
       startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); 
      } 
     }); 



    } 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent intent) 
    { 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
     { 
      if (requestCode == REQUEST_SELECT_FILE) 
      { 
       if (uploadMessage == null) 
        return; 
       uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent)); 
       uploadMessage = null; 
      } 
     } 
     else if (requestCode == FILECHOOSER_RESULTCODE) 
     { 
      if (null == mUploadMessage) 
       return; 
      // Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment 
      // Use RESULT_OK only if you're implementing WebView inside an Activity 
      Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData(); 
      mUploadMessage.onReceiveValue(result); 
      mUploadMessage = null; 
     } 
     else 
      Toast.makeText(MainActivity.this.getApplicationContext(), "Failed to Upload Image", Toast.LENGTH_LONG).show(); 
    } 

確保啓用這個權限在AndroidManifest.xml中更新以下行

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
     <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" /> 
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

它爲我試圖用這個代碼。

+0

這可行,但它只允許我上傳視頻,它也沒有提出相機選項,而只是打開文件選擇器。 – TheLearner 2017-09-21 05:25:48

+0

那你究竟需要什麼,如果你明確告訴它會有幫助的@ TheLearner – 2017-09-21 07:53:37

+0

我需要的是通過webview將圖像和視頻上傳到網站。如果用戶決定使用他們的相機拍攝他們上傳的照片,並且他們選擇了要上傳到網絡視圖的圖片/視頻,我希望這樣做。 – TheLearner 2017-09-21 15:26:58