Je développe une Android. Fondamentalement, il s'agit d'un WebView
et d'un progressBar. Le site mobile de Facebook (m.facebook.com) est chargé dans le WebView
.
Lorsque je clique sur le bouton Choisir un fichier pour télécharger une image, rien ne se passe. J'ai essayé TOUTES les solutions et aucune ne fonctionne. Je teste un Galaxy Note (GT-N7000) exécutant 4.0.3. Ma version minimale du SDK est la version 8.
(source: istyla.com )
Voici mon code pour plus d'informations ...
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;
}
}
Merci
Voici comment j'utilise dans mon application
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;
}
référence de Mike Olivier partagé par Fr33dan est important. Je partage ce qui a fonctionné pour moi dans une situation assez semblable à la vôtre.
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, "" );
}
});
REMARQUE: j'ai trouvé cela quelque part dans le débordement de la pile et blog de m0s .
Ignorez également les avertissements relatifs aux peluches. Celui-ci fonctionne assez bien pour l'API 8 et les versions ultérieures.
Ce code vous aidera à résoudre le problème
Mettez simplement à jour le fichier MainActivity.Java avec le code ci-dessous
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();
}
Assurez-vous d'activer l'autorisation dans la mise à jour AndroidManifest.xml des lignes suivantes
<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" />
Cela a fonctionné pour moi d'essayer avec ce code.
Étant donné le nombre élevé de votes, je suppose que personne n'a remarqué que le troisième commentaire (de David Esteves ) contient n lien avec pour répondre à cette question.
Michel Olivier dit:
Cette solution fonctionne également pour le nid d'abeille et le sandwich à la crème glacée. On dirait que Google a introduit une nouvelle fonctionnalité intéressante (accepter l'attribut) et a oublié d'implémenter une surcharge pour une compatibilité descendante.
Il vous suffit donc d'ajouter une surcharge openFileChooser
à votre classe MyWebChromeClient
qui accepte le paramètre de chaîne, puis d'appeler celui qui ne le fait pas:
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType )
{
this.openFileChooser(uploadMsg);
}
Ce faisant, j'ai pu faire fonctionner votre code comme prévu.
Lorsque vous appelez AlertDialog dans WebChromeClient.OpenFileChooser, vous devez informer Webchrome qu'aucune sélection n'a été effectuée en cas de bouton de retour. Comme le bouton Retour peut être enfoncé dans votre boîte de dialogue, vous devez gérer OnCancel de la boîte de dialogue et indiquer à WebChrome que la sélection est terminée.
par exemple:
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();