From d7bd9789ddb7f7f76ea7320e647fdd737a66eb02 Mon Sep 17 00:00:00 2001
From: Andrey Beskrovnykh <andrey.beskrovnykh@yandex.ru>
Date: Thu, 22 Nov 2018 21:23:36 +0700
Subject: [PATCH 1/4] Fix can't import sjr

---
 .../app/src/main/AndroidManifest.xml          |  5 ++-
 .../scratchjr/android/ScratchJrActivity.java  | 37 ++++++++++++++++---
 2 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/android/ScratchJr/app/src/main/AndroidManifest.xml b/android/ScratchJr/app/src/main/AndroidManifest.xml
index 0927de2..32f68ca 100644
--- a/android/ScratchJr/app/src/main/AndroidManifest.xml
+++ b/android/ScratchJr/app/src/main/AndroidManifest.xml
@@ -7,7 +7,7 @@
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
-
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 
     <uses-feature android:name="android.hardware.camera" android:required="false" />
     <uses-feature android:name="android.hardware.microphone" android:required="false" />
@@ -40,7 +40,8 @@
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
-                <data android:mimeType="@string/share_mimetype" />
+                <data android:scheme="file" />
+                <data android:mimeType="*/*" />
                 <data android:pathPattern="@string/share_extension_filter" />
                 <data android:host="*" />
             </intent-filter>
diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
index 92ef32e..131ad38 100644
--- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
+++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
@@ -4,6 +4,7 @@ import android.Manifest;
 import android.animation.ObjectAnimator;
 import android.annotation.SuppressLint;
 import android.app.Activity;
+import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -37,6 +38,8 @@ import com.google.android.gms.analytics.HitBuilders;
 import com.google.android.gms.analytics.Tracker;
 
 import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -147,9 +150,8 @@ public class ScratchJrActivity
         CookieManager.getInstance().setAcceptCookie(true);
         CookieManager.setAcceptFileSchemeCookies(true);
 
-        String PROJECT_MIMETYPE = getApplicationContext().getString(R.string.share_mimetype);
         Intent it = getIntent();
-        if (it != null && it.getType() != null && it.getType().equals(PROJECT_MIMETYPE)) {
+        if (it != null && it.getData() != null) {
             receiveProject(it.getData());
         }
 
@@ -171,11 +173,20 @@ public class ScratchJrActivity
                 }, 1000);
             }
         });
-
         requestPermissions();
     }
 
+    private void requestExtStoragePermissions() {
+        int readExtPermissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
+        if (readExtPermissionResult != PackageManager.PERMISSION_GRANTED) {
+            int requestCode = 2;
+            ActivityCompat.requestPermissions(this,
+                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, requestCode);
+        }
+    }
+
     public void requestPermissions() {
+        requestExtStoragePermissions();
         cameraPermissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
         micPermissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);
 
@@ -293,17 +304,31 @@ public class ScratchJrActivity
     @Override
     protected void onNewIntent(Intent it) {
         super.onNewIntent(it);
-        String PROJECT_MIMETYPE = getApplicationContext().getString(R.string.share_mimetype);
-        if (it != null && it.getType() != null && it.getType().equals(PROJECT_MIMETYPE)) {
+        if (it != null && it.getData() != null) {
             receiveProject(it.getData());
         }
     }
 
     private void receiveProject(Uri projectUri) {
+        File projectFile = null;
+        String scheme = projectUri.getScheme();
+        if (scheme != null) {
+            if (scheme.equals(ContentResolver.SCHEME_FILE)) {
+                String filePath = projectUri.getPath();
+                projectFile = filePath != null ? new File(filePath) : null;
+            } else if (!scheme.equals(ContentResolver.SCHEME_CONTENT)) {
+                return;
+            }
+        }
         // Read the project one byte at a time into a buffer
         ByteArrayOutputStream projectData = new ByteArrayOutputStream();
         try {
-            InputStream is = getContentResolver().openInputStream(projectUri);
+            InputStream is = null;
+            if (projectFile != null) {
+                is = new FileInputStream(projectFile);
+            } else {
+                getContentResolver().openInputStream(projectUri);
+            }
             byte[] readByte = new byte[1];
             while ((is.read(readByte)) == 1) {
                 projectData.write(readByte[0]);

From 1a2433885df27e641ce769c5e46bd63f9d464627 Mon Sep 17 00:00:00 2001
From: Andrey Beskrovnykh <andrey.beskrovnykh@yandex.ru>
Date: Fri, 23 Nov 2018 10:50:56 +0700
Subject: [PATCH 2/4] Fix possible backward compatibility issue

---
 android/ScratchJr/app/src/main/AndroidManifest.xml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/android/ScratchJr/app/src/main/AndroidManifest.xml b/android/ScratchJr/app/src/main/AndroidManifest.xml
index 32f68ca..80371e0 100644
--- a/android/ScratchJr/app/src/main/AndroidManifest.xml
+++ b/android/ScratchJr/app/src/main/AndroidManifest.xml
@@ -45,6 +45,14 @@
                 <data android:pathPattern="@string/share_extension_filter" />
                 <data android:host="*" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:mimeType="@string/share_mimetype" />
+                <data android:pathPattern="@string/share_extension_filter" />
+                <data android:host="*" />
+            </intent-filter>
         </activity>
 
         <receiver android:name="com.google.android.gms.analytics.AnalyticsReceiver"

From bbba46c143e20b18f7362988886e875d10cb3b7f Mon Sep 17 00:00:00 2001
From: Andrey Beskrovnykh <andrey.beskrovnykh@yandex.ru>
Date: Fri, 23 Nov 2018 19:21:01 +0700
Subject: [PATCH 3/4] Add forgotten input stream initialization

---
 .../java/org/scratchjr/android/ScratchJrActivity.java    | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
index 131ad38..8594cd3 100644
--- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
+++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
@@ -323,12 +323,9 @@ public class ScratchJrActivity
         // Read the project one byte at a time into a buffer
         ByteArrayOutputStream projectData = new ByteArrayOutputStream();
         try {
-            InputStream is = null;
-            if (projectFile != null) {
-                is = new FileInputStream(projectFile);
-            } else {
-                getContentResolver().openInputStream(projectUri);
-            }
+            InputStream is = (projectFile != null) ? new FileInputStream(projectFile) :
+                    getContentResolver().openInputStream(projectUri);
+            
             byte[] readByte = new byte[1];
             while ((is.read(readByte)) == 1) {
                 projectData.write(readByte[0]);

From 9a12f98cf937d6941025888489ed4b69db38bb57 Mon Sep 17 00:00:00 2001
From: Chris Garrity <chrisg@media.mit.edu>
Date: Tue, 7 Apr 2020 14:49:55 -0400
Subject: [PATCH 4/4] Add checks for filetype, skip unnecessary FileIO
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This PR was 95% of the way there, and I didn’t want to ask for changes after not getting to review it for so long, so I just made the changes.

Thanks for submitting!
---
 android/ScratchJr/app/build.gradle            |  2 +-
 .../app/src/main/AndroidManifest.xml          |  4 +++-
 .../scratchjr/android/ScratchJrActivity.java  | 19 +++++++------------
 3 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/android/ScratchJr/app/build.gradle b/android/ScratchJr/app/build.gradle
index e7bce47..95e6a69 100644
--- a/android/ScratchJr/app/build.gradle
+++ b/android/ScratchJr/app/build.gradle
@@ -19,7 +19,7 @@ android {
         free {
             applicationId "org.scratchjr.androidfree"
             minSdkVersion 19
-            targetSdkVersion 27
+            targetSdkVersion 28
             versionCode 21
             versionName "1.2.0"
         }
diff --git a/android/ScratchJr/app/src/main/AndroidManifest.xml b/android/ScratchJr/app/src/main/AndroidManifest.xml
index 80371e0..8626329 100644
--- a/android/ScratchJr/app/src/main/AndroidManifest.xml
+++ b/android/ScratchJr/app/src/main/AndroidManifest.xml
@@ -41,6 +41,7 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
                 <data android:scheme="file" />
+                <data android:scheme="content" />
                 <data android:mimeType="*/*" />
                 <data android:pathPattern="@string/share_extension_filter" />
                 <data android:host="*" />
@@ -49,8 +50,9 @@
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="file" />
+                <data android:scheme="content" />
                 <data android:mimeType="@string/share_mimetype" />
-                <data android:pathPattern="@string/share_extension_filter" />
                 <data android:host="*" />
             </intent-filter>
         </activity>
diff --git a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
index 8594cd3..2dcc7b2 100644
--- a/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
+++ b/android/ScratchJr/app/src/main/java/org/scratchjr/android/ScratchJrActivity.java
@@ -38,8 +38,6 @@ import com.google.android.gms.analytics.HitBuilders;
 import com.google.android.gms.analytics.Tracker;
 
 import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -310,21 +308,18 @@ public class ScratchJrActivity
     }
 
     private void receiveProject(Uri projectUri) {
-        File projectFile = null;
+        String PROJECT_EXTENSION = getApplicationContext().getString(R.string.share_extension_filter);
         String scheme = projectUri.getScheme();
-        if (scheme != null) {
-            if (scheme.equals(ContentResolver.SCHEME_FILE)) {
-                String filePath = projectUri.getPath();
-                projectFile = filePath != null ? new File(filePath) : null;
-            } else if (!scheme.equals(ContentResolver.SCHEME_CONTENT)) {
-                return;
-            }
+        Log.i(LOG_TAG, "receiveProject(scheme): " + scheme);
+        Log.i(LOG_TAG, "receiveProject(path): " + projectUri.getPath());
+        if (scheme == null || !(scheme.equals(ContentResolver.SCHEME_FILE) || scheme.equals(ContentResolver.SCHEME_CONTENT)) ||
+                !projectUri.getPath().matches(PROJECT_EXTENSION)) {
+            return;
         }
         // Read the project one byte at a time into a buffer
         ByteArrayOutputStream projectData = new ByteArrayOutputStream();
         try {
-            InputStream is = (projectFile != null) ? new FileInputStream(projectFile) :
-                    getContentResolver().openInputStream(projectUri);
+            InputStream is = getContentResolver().openInputStream(projectUri);
             
             byte[] readByte = new byte[1];
             while ((is.read(readByte)) == 1) {