|  | @@ -1,24 +1,32 @@
 | 
	
		
			
			| 1 | 1 |  
 | 
	
		
			
			| 2 | 2 |  package com.reactnativecommunity.webview;
 | 
	
		
			
			| 3 | 3 |  
 | 
	
		
			
			|  | 4 | +import android.Manifest;
 | 
	
		
			
			| 4 | 5 |  import android.app.Activity;
 | 
	
		
			
			|  | 6 | +import android.app.DownloadManager;
 | 
	
		
			
			|  | 7 | +import android.content.Context;
 | 
	
		
			
			| 5 | 8 |  import android.content.Intent;
 | 
	
		
			
			|  | 9 | +import android.content.pm.PackageManager;
 | 
	
		
			
			| 6 | 10 |  import android.net.Uri;
 | 
	
		
			
			| 7 | 11 |  import android.os.Build;
 | 
	
		
			
			| 8 | 12 |  import android.os.Environment;
 | 
	
		
			
			| 9 | 13 |  import android.os.Parcelable;
 | 
	
		
			
			| 10 | 14 |  import android.provider.MediaStore;
 | 
	
		
			
			| 11 | 15 |  import android.support.annotation.RequiresApi;
 | 
	
		
			
			|  | 16 | +import android.support.v4.content.ContextCompat;
 | 
	
		
			
			| 12 | 17 |  import android.support.v4.content.FileProvider;
 | 
	
		
			
			| 13 | 18 |  import android.util.Log;
 | 
	
		
			
			| 14 | 19 |  import android.webkit.ValueCallback;
 | 
	
		
			
			| 15 | 20 |  import android.webkit.WebChromeClient;
 | 
	
		
			
			|  | 21 | +import android.widget.Toast;
 | 
	
		
			
			| 16 | 22 |  
 | 
	
		
			
			| 17 | 23 |  import com.facebook.react.bridge.ActivityEventListener;
 | 
	
		
			
			| 18 | 24 |  import com.facebook.react.bridge.Promise;
 | 
	
		
			
			| 19 | 25 |  import com.facebook.react.bridge.ReactApplicationContext;
 | 
	
		
			
			| 20 | 26 |  import com.facebook.react.bridge.ReactContextBaseJavaModule;
 | 
	
		
			
			| 21 | 27 |  import com.facebook.react.bridge.ReactMethod;
 | 
	
		
			
			|  | 28 | +import com.facebook.react.modules.core.PermissionAwareActivity;
 | 
	
		
			
			|  | 29 | +import com.facebook.react.modules.core.PermissionListener;
 | 
	
		
			
			| 22 | 30 |  
 | 
	
		
			
			| 23 | 31 |  import java.io.File;
 | 
	
		
			
			| 24 | 32 |  import java.io.IOException;
 | 
	
	
		
			
			|  | @@ -38,6 +46,9 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
 | 
	
		
			
			| 38 | 46 |    private ValueCallback<Uri[]> filePathCallback;
 | 
	
		
			
			| 39 | 47 |    private Uri outputFileUri;
 | 
	
		
			
			| 40 | 48 |  
 | 
	
		
			
			|  | 49 | +  private DownloadManager.Request downloadRequest;
 | 
	
		
			
			|  | 50 | +  private static final int FILE_DOWNLOAD_PERMISSION_REQUEST = 1;
 | 
	
		
			
			|  | 51 | +
 | 
	
		
			
			| 41 | 52 |    final String DEFAULT_MIME_TYPES = "*/*";
 | 
	
		
			
			| 42 | 53 |  
 | 
	
		
			
			| 43 | 54 |    public RNCWebViewModule(ReactApplicationContext reactContext) {
 | 
	
	
		
			
			|  | @@ -177,6 +188,37 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
 | 
	
		
			
			| 177 | 188 |      return true;
 | 
	
		
			
			| 178 | 189 |    }
 | 
	
		
			
			| 179 | 190 |  
 | 
	
		
			
			|  | 191 | +  public void setDownloadRequest(DownloadManager.Request request) {
 | 
	
		
			
			|  | 192 | +    this.downloadRequest = request;
 | 
	
		
			
			|  | 193 | +  }
 | 
	
		
			
			|  | 194 | +
 | 
	
		
			
			|  | 195 | +  public void downloadFile() {
 | 
	
		
			
			|  | 196 | +    DownloadManager dm = (DownloadManager) getCurrentActivity().getBaseContext().getSystemService(Context.DOWNLOAD_SERVICE);
 | 
	
		
			
			|  | 197 | +    String downloadMessage = "Downloading";
 | 
	
		
			
			|  | 198 | +
 | 
	
		
			
			|  | 199 | +    dm.enqueue(this.downloadRequest);
 | 
	
		
			
			|  | 200 | +
 | 
	
		
			
			|  | 201 | +    Toast.makeText(getCurrentActivity().getApplicationContext(), downloadMessage, Toast.LENGTH_LONG).show();
 | 
	
		
			
			|  | 202 | +  }
 | 
	
		
			
			|  | 203 | +
 | 
	
		
			
			|  | 204 | +  public boolean grantFileDownloaderPermissions() {
 | 
	
		
			
			|  | 205 | +    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
 | 
	
		
			
			|  | 206 | +      return true;
 | 
	
		
			
			|  | 207 | +    }
 | 
	
		
			
			|  | 208 | +
 | 
	
		
			
			|  | 209 | +    boolean result = true;
 | 
	
		
			
			|  | 210 | +    if (ContextCompat.checkSelfPermission(getCurrentActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
 | 
	
		
			
			|  | 211 | +      result = false;
 | 
	
		
			
			|  | 212 | +    }
 | 
	
		
			
			|  | 213 | +
 | 
	
		
			
			|  | 214 | +    if (!result) {
 | 
	
		
			
			|  | 215 | +      PermissionAwareActivity activity = getPermissionAwareActivity();
 | 
	
		
			
			|  | 216 | +      activity.requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE }, FILE_DOWNLOAD_PERMISSION_REQUEST, webviewFileDownloaderPermissionListener);
 | 
	
		
			
			|  | 217 | +    }
 | 
	
		
			
			|  | 218 | +
 | 
	
		
			
			|  | 219 | +    return result;
 | 
	
		
			
			|  | 220 | +  }
 | 
	
		
			
			|  | 221 | +
 | 
	
		
			
			| 180 | 222 |    public RNCWebViewPackage getPackage() {
 | 
	
		
			
			| 181 | 223 |      return this.aPackage;
 | 
	
		
			
			| 182 | 224 |    }
 | 
	
	
		
			
			|  | @@ -306,4 +348,34 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
 | 
	
		
			
			| 306 | 348 |      // will be an array with one empty string element, afaik
 | 
	
		
			
			| 307 | 349 |      return arr.length == 0 || (arr.length == 1 && arr[0].length() == 0);
 | 
	
		
			
			| 308 | 350 |    }
 | 
	
		
			
			|  | 351 | +
 | 
	
		
			
			|  | 352 | +  private PermissionAwareActivity getPermissionAwareActivity() {
 | 
	
		
			
			|  | 353 | +    Activity activity = getCurrentActivity();
 | 
	
		
			
			|  | 354 | +    if (activity == null) {
 | 
	
		
			
			|  | 355 | +        throw new IllegalStateException("Tried to use permissions API while not attached to an Activity.");
 | 
	
		
			
			|  | 356 | +    } else if (!(activity instanceof PermissionAwareActivity)) {
 | 
	
		
			
			|  | 357 | +        throw new IllegalStateException("Tried to use permissions API but the host Activity doesn't implement PermissionAwareActivity.");
 | 
	
		
			
			|  | 358 | +    }
 | 
	
		
			
			|  | 359 | +    return (PermissionAwareActivity) activity;
 | 
	
		
			
			|  | 360 | +  }
 | 
	
		
			
			|  | 361 | +
 | 
	
		
			
			|  | 362 | +  private PermissionListener webviewFileDownloaderPermissionListener = new PermissionListener() {
 | 
	
		
			
			|  | 363 | +    @Override
 | 
	
		
			
			|  | 364 | +    public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
 | 
	
		
			
			|  | 365 | +      switch (requestCode) {
 | 
	
		
			
			|  | 366 | +        case FILE_DOWNLOAD_PERMISSION_REQUEST: {
 | 
	
		
			
			|  | 367 | +          // If request is cancelled, the result arrays are empty.
 | 
	
		
			
			|  | 368 | +          if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
 | 
	
		
			
			|  | 369 | +            if (downloadRequest != null) {
 | 
	
		
			
			|  | 370 | +              downloadFile();
 | 
	
		
			
			|  | 371 | +            }
 | 
	
		
			
			|  | 372 | +          } else {
 | 
	
		
			
			|  | 373 | +            Toast.makeText(getCurrentActivity().getApplicationContext(), "Cannot download files as permission was denied. Please provide permission to write to storage, in order to download files.", Toast.LENGTH_LONG).show();
 | 
	
		
			
			|  | 374 | +          }
 | 
	
		
			
			|  | 375 | +          return true;
 | 
	
		
			
			|  | 376 | +        }
 | 
	
		
			
			|  | 377 | +      }
 | 
	
		
			
			|  | 378 | +      return false;
 | 
	
		
			
			|  | 379 | +    }
 | 
	
		
			
			|  | 380 | +  };
 | 
	
		
			
			| 309 | 381 |  }
 |