How to implement marshmallow read external storage permission for this activity please

1k views Asked by At

Hello I am making a webview app for my website. That site have a file chooser, upto lollipop, uploading working, no problem, in manifest I have given read external storage permission, but I know new marshmallow need request permission show. So how to implement that (ask user to allow read external storage for file upload) in this activity, suppose this is my main activity for upload page webview. Main2Activity is that activity page which deals with upload page webview

Main2Activity.java code:

package com.mywebsite.mywebsite;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;

import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;

import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;

import java.util.Date;

public class Main2Activity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener{
WebView webView;

private static final String TAG = Main2Activity.class.getSimpleName();
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private final static int FCR=1;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
    super.onActivityResult(requestCode, resultCode, intent);
    if(Build.VERSION.SDK_INT >= 21){
        Uri[] results = null;
        //Check if response is positive
        if(resultCode== Activity.RESULT_OK){
            if(requestCode == FCR){
                if(null == mUMA){
                    return;
                }
                if(intent == null){
                    //Capture Photo if no image available
                    if(mCM != null){
                        results = new Uri[]{Uri.parse(mCM)};
                    }
                }else{
                    String dataString = intent.getDataString();
                    if(dataString != null){
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                }
            }
        }
        mUMA.onReceiveValue(results);
        mUMA = null;
    }else{
        if(requestCode == FCR){
            if(null == mUM) return;
            Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();
            mUM.onReceiveValue(result);
            mUM = null;
        }
    }
}

@SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
@Override
protected void onCreate(Bundle savedInstanceState)   {


    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);



    //new code start
    Toolbar toolbar2 = (Toolbar) findViewById(R.id.toolbar2);
    setSupportActionBar(toolbar2);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout2);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar2, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view2);
    navigationView.setNavigationItemSelectedListener(this);
    //new code end
    webView = (WebView) findViewById(R.id.main2);
    assert webView != null;
    WebSettings webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setAllowFileAccess(true);

    if(Build.VERSION.SDK_INT >= 21){
        webSettings.setMixedContentMode(0);
        webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }else 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.setWebViewClient(new Callback());
    webView.setWebViewClient(new CustomWebViewClient());

    webView.loadUrl("http://path to upload page");




    webView.setWebChromeClient(new WebChromeClient(){



        //For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg){
            mUM = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            Main2Activity.this.startActivityForResult(Intent.createChooser(i,"File Chooser"), FCR);
        }
        // For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
        public void openFileChooser(ValueCallback uploadMsg, String acceptType){
            mUM = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            Main2Activity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FCR);
        }
        //For Android 4.1+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            mUM = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("image/*");
            Main2Activity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), Main2Activity.FCR);
        }
        //For Android 5.0+
        public boolean onShowFileChooser(
                WebView webView, ValueCallback<Uri[]> filePathCallback,
                WebChromeClient.FileChooserParams fileChooserParams){
            if(mUMA != null){
                mUMA.onReceiveValue(null);
            }
            mUMA = filePathCallback;
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if(takePictureIntent.resolveActivity(Main2Activity.this.getPackageManager()) != null){
                File photoFile = null;
                try{
                    photoFile = createImageFile();
                    takePictureIntent.putExtra("PhotoPath", mCM);
                }catch(IOException ex){
                    Log.e(TAG, "Image file creation failed", ex);
                }
                if(photoFile != null){
                    mCM = "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, FCR);
            return true;
        }
    });
}
//new code start
@Override
public boolean onCreateOptionsMenu(Menu menu2) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main2, menu2);
    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_settings2) {
        Intent i = new Intent(Main2Activity.this, MainActivity.class);
        startActivity(i);

    }


    return super.onOptionsItemSelected(item);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_local) {
        // Handle the camera action
        webView.loadUrl("http://example.com/index.php?/category/1&mobile=true");
    } else if (id == R.id.nav_spices2) {
        webView.loadUrl("http://example.com/index.php?/category/84&mobile=true");
    } else if (id == R.id.nav_vherbarium2) {
        webView.loadUrl("http://example.com/index.php?/category/36&mobile=true");
    } else if (id == R.id.nav_usersupload2) {
        webView.loadUrl("http://example.com/index.php?/category/user&mobile=true");
    } else if (id == R.id.nav_recent2) {
        webView.loadUrl("http://example.com/index.php?/recent_pics&mobile=true");
    } else if (id == R.id.nav_login2) {
        webView.loadUrl("http://example.com/identification.php?mobile=true");
    } else if (id == R.id.nav_register2) {
        webView.loadUrl("http://example.com/register.php?mobile=true");
    } else if (id == R.id.nav_search2) {
        webView.loadUrl("http://example.com/search.php?mobile=true");
    } else if (id == R.id.nav_contact2) {
        webView.loadUrl("http://example.com/index.php?/contact/&mobile=true");
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout2);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

public class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        if(url.contains("something")) return true;
        return false; //Default is to not override unless our condition is met.
    }
    public void onPageFinished(WebView webView, String url) {

        String webUrl = webView.getUrl();
        System.out.println(webUrl);
        if(url.startsWith("http://example/oAuth/auth.php?provider=Facebook&openid_identifier=&init_auth=1#_=_")){
            String redirectUrl = "http:/// link to upload page.php";
            webView.loadUrl(redirectUrl);
            return;
        }
        super.onPageFinished(webView, url);
    }
}





//new code end




public class Callback extends WebViewClient {
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
        Toast.makeText(getApplicationContext(), "Failed loading app! Check internet connection", Toast.LENGTH_SHORT).show();
    }
}
// Create an image file
private File createImageFile() throws IOException{
    @SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "img_"+timeStamp+"_";
    File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(imageFileName,".jpg",storageDir);
}
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event){
    if(event.getAction() == KeyEvent.ACTION_DOWN){
        switch(keyCode){
            case KeyEvent.KEYCODE_BACK:
                if(webView.canGoBack()){
                    webView.goBack();
                }else{
                    finish();
                }
                return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}



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

There are 1 answers

2
Noel Bautista On

Check permissions like so (source):

public  boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            Log.v(TAG,"Permission is granted");
            return true;
        } else {

            Log.v(TAG,"Permission is revoked");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        Log.v(TAG,"Permission is granted");
        return true;
    }
}

Also implement the permission callback:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
        Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
        //resume tasks needing this permission
    }
}

For easier permission handling across all Android versions, check out this awesome third party library called PermissionsDispatcher by Hotchemi.