내 Android webview 앱에 대한 팝업을 얻을 수 없었습니다. 누군가가 나를 도울 수있는 가능한 모든 것을 시도했습니다. 여기 내 mainActivity 코드가 있습니다.
내가하려는 것은 성공적으로 얻은 내 webview를로드하는 것이지만 사용자가 프로필 사진을 클릭하면 카메라를 열거 나 갤러리에서 이미지를로드하라는 메시지가 표시되고 다시 누르면 업로드 옵션이있는 private 페이지가 있습니다. 사진을 업로드하거나 카메라를 열 때도 똑같은 일이 발생해야합니다. 내 브라우저에서 수행하지만 webview android 앱에서 수행하지 않으면 제대로 작동합니다.
public class MainActivity extends AppCompatActivity {
private static final int MY_BLINK_ID_REQUEST_CODE = 0x101;
public static final int REQUEST_PERMISSION_READ_EXTERNAL_STORAGE = 101;
private static final int REQUEST_WEBFORM = 300;
public static final int REQUEST_SELECT_FILE = 100;
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> uploadMessageLP;
private Uri directUploadImageUri;
private static final String TAG = MainActivity.class.getSimpleName();
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupToolbar();
loadHtml();
}
public void cancelFileUpload() {
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
}
if (uploadMessageLP != null) {
uploadMessageLP.onReceiveValue(null);
uploadMessageLP = null;
}
this.directUploadImageUri = null;
}
public void setUploadMessageLP(ValueCallback<Uri[]> uploadMessageLP) {
this.uploadMessageLP = uploadMessageLP;
}
/**
* setup toolbar
*/
private void setupToolbar() {
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//change title color
toolbar.setTitleTextColor(ContextCompat.getColor(this, R.color.white));
//set title
getSupportActionBar().setTitle(getString(R.string.app_name));
}
private void loadHtml() {
mWebView = (WebView) findViewById(R.id.wv);
mWebView.setWebViewClient(new WebViewClient());
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
settings.setAllowContentAccess(true);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
// Render the HTML file on WebView
mWebView.loadUrl("http://new.techyardnepal.com");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_favorite) {
startOCRScan();
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* start ocr on scan id click
*/
private void startOCRScan() {
// Intent for MyScanActivity
Intent intent = new Intent(this, MRPScanActivity.class);
startActivityForResult(intent, MY_BLINK_ID_REQUEST_CODE);
}
/**
* This method is called whenever control is returned from activity started with
* startActivityForResult.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// onActivityResult is called whenever we are returned from activity started
// with startActivityForResult. We need to check request code to determine
// that we have really returned from BlinkID activity.
if (requestCode == MY_BLINK_ID_REQUEST_CODE) {
if (resultCode == MRPScanActivity.RESULT_OK && data != null) {
// depending on settings, we may have multiple scan results.
// we first need to obtain recognition results
RecognitionResults results = data.getParcelableExtra(ScanActivity.EXTRAS_RECOGNITION_RESULTS);
BaseRecognitionResult[] resArray = null;
if (results != null) {
// get array of recognition results
resArray = results.getRecognitionResults();
}
if (resArray != null) {
Log.i(TAG, "Data count: " + resArray.length);
int i = 1;
for (BaseRecognitionResult res : resArray) {
Log.i(TAG, "Data #" + Integer.valueOf(i++).toString());
// Each element in resultArray inherits BaseRecognitionResult class and
// represents the scan result of one of activated recognizers that have
// been set up.
res.log();
}
} else {
Log.e(TAG, "Unable to retrieve recognition data!");
}
data.setComponent(new ComponentName(this, ResultActivity.class));
startActivity(data);
}
}
if (data != null && data.getBooleanExtra("exit", false))
finish();
if (requestCode == REQUEST_SELECT_FILE) {
if (resultCode != RESULT_OK) {
cancelFileUpload();
return;
}
// from documents (and video camera)
if (data != null && data.getData() != null) {
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(data.getData());
mUploadMessage = null;
}
return;
}
// we may get clip data for multi-select documents
if (data != null && data.getClipData() != null) {
ClipData clipData = data.getClipData();
ArrayList<Uri> files = new ArrayList<>(clipData.getItemCount());
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
if (item.getUri() != null) {
files.add(item.getUri());
}
}
if (mUploadMessage != null) {
// shouldn never happen, but just in case, send the first item
if (files.size() > 0) {
mUploadMessage.onReceiveValue(files.get(0));
} else {
mUploadMessage.onReceiveValue(null);
}
mUploadMessage = null;
}
if (uploadMessageLP != null) {
uploadMessageLP.onReceiveValue(files.toArray(new Uri[files.size()]));
uploadMessageLP = null;
}
return;
}
// from camera
if (this.directUploadImageUri != null) {
// check if we have external storage permissions
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_PERMISSION_READ_EXTERNAL_STORAGE);
// wait for the onRequestPermissionsResult callback
return;
}
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(this.directUploadImageUri);
mUploadMessage = null;
}
if (uploadMessageLP != null) {
uploadMessageLP.onReceiveValue(new Uri[]{this.directUploadImageUri});
uploadMessageLP = null;
}
this.directUploadImageUri = null;
return;
}
// Should not reach here.
cancelFileUpload();
}
}
}
다음 코드 시도 :
public class MainActivity extends Activity {
private RelativeLayout mLayout;
private ProgressBar progressBar;
private WebView webView;
String loadUrl;
private static final int INPUT_FILE_REQUEST_CODE = 1;
private static final int FILECHOOSER_RESULTCODE = 1;
private static final String TAG = MainActivity.class.getSimpleName();
private WebSettings webSettings;
private ValueCallback<Uri> mUploadMessage;
private Uri mCapturedImageURI = null;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
ValueCallback<Uri[]> chooserPathUri;
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
WebView chooserWV;
WebChromeClient.FileChooserParams chooserParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadUrl = "https:google.com";
mLayout = (RelativeLayout) findViewById(R.id.activity_main);
progressBar = (ProgressBar)findViewById(R.id.indicator);
webView = (WebView) findViewById(R.id.webView);
webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setDomStorageEnabled(true);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setAllowFileAccess(true);
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
else if(Build.VERSION.SDK_INT >=11 && Build.VERSION.SDK_INT < 19) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.setWebChromeClient(new ChromeClient());
webView.loadUrl(loadUrl); //change with your website
this.webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.INVISIBLE);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressBar.setVisibility(View.VISIBLE);
}
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return handleUrl(url);
}
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
final Uri uri = request.getUrl();
return handleUrl(request.getUrl().toString());
}
});
}
public boolean handleUrl(String url){
if (url.startsWith("geo:") || url.startsWith("mailto:") || url.startsWith("tel:") || url.startsWith("sms:")) {
Intent searchAddress = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(searchAddress);
}else
webView.loadUrl(url);
return true;
}
private boolean checkAndRequestPermissions() {
int permissionCamera = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int permissionStorage = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionStorage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissionCamera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
Log.e(TAG, "Returned falseeeee-------");
return false;
}
Log.d(TAG, "Permission returned trueeeee-------");
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "camera & Storage permission granted");
Toast.makeText(this, "Permissions granted! Try now.", Toast.LENGTH_SHORT).show();
//chromClt.openChooser(chooserWV, chooserPathUri, chooserParams);
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showDialogOK("Camera and Storage Permission required for this app",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG).show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
break;
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
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) {
// 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)};
}else {
if (Build.VERSION.SDK_INT >= 16) {
if (data.getClipData() != null) {
final int numSelectedFiles = data.getClipData().getItemCount();
results = new Uri[numSelectedFiles];
for (int i = 0; i < numSelectedFiles; i++) {
results[i] = data.getClipData().getItemAt(i).getUri();
}
}
}
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == this.mUploadMessage) {
return;
}
Uri result = null;
try {
if (resultCode != RESULT_OK) {
result = null;
} else {
// retrieve from the private variable if the intent is null
result = data == null ? mCapturedImageURI : data.getData();
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "activity :" + e,
Toast.LENGTH_LONG).show();
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
return;
}
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;
}
public class ChromeClient extends WebChromeClient {
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
// callback.invoke(String origin, boolean allow, boolean remember);
Log.e(TAG, "onGeolocationPermissionsShowPrompt: " );
callback.invoke(origin, true, false);
}
// For Android 5.0
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
chooserWV = view;
chooserPathUri = filePath;
chooserParams = fileChooserParams;
if(checkAndRequestPermissions()){
openChooser(chooserWV, chooserPathUri, chooserParams);
return true;
}else {
return false;
}
}
public void openChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams){
// Double check that we don't have any existing callbacks
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePath;
Intent takePictureIntent;
takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
Log.e(TAG, "Unable to create Image File", ex);
}
// Continue only if the File was successfully created
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);
if (Build.VERSION.SDK_INT >= 18) {
contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
contentSelectionIntent.setType("*/*");
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);
}
// openFileChooser for Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
mUploadMessage = uploadMsg;
// Create AndroidExampleFolder at sdcard
// Create AndroidExampleFolder at sdcard
File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
, "AndroidExampleFolder");
if (!imageStorageDir.exists()) {
// Create AndroidExampleFolder at sdcard
imageStorageDir.mkdirs();
}
// Create camera captured image file path and name
File file = new File(
imageStorageDir + File.separator + "IMG_"
+ String.valueOf(System.currentTimeMillis())
+ ".jpg");
mCapturedImageURI = Uri.fromFile(file);
// Camera capture image intent
final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
// Create file chooser intent
Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
// Set camera intent to file chooser
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
// On select image call onActivityResult method of activity
chooserIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
// openFileChooser for Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
//openFileChooser for other Android versions
public void openFileChooser(ValueCallback<Uri> uploadMsg,
String acceptType,
String capture) {
openFileChooser(uploadMsg, acceptType);
}
}
@SuppressLint("NewApi")
@Override
protected void onResume() {
super.onResume();
webView.onResume();
// ...
}
@SuppressLint("NewApi")
@Override
protected void onPause() {
webView.onPause();
// ...
super.onPause();
}
int mExit = 0;
@Override
public void onBackPressed() {
if(webView.canGoBack()) {
webView.goBack();
} else {
super.onBackPressed();
}
}
매니페스트에 권한을 추가하는 것을 잊지 마세요.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>