Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Commit

Permalink
Merge pull request #391 from OkunaOrg/release/0.0.52
Browse files Browse the repository at this point in the history
Release/0.0.52
  • Loading branch information
lifenautjoe authored Sep 20, 2019
2 parents dd1a8e1 + 928c50a commit 682655d
Show file tree
Hide file tree
Showing 422 changed files with 48,254 additions and 19,720 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ build_apk_prod:

generate_locale:
flutter pub pub run intl_translation:extract_to_arb --output-dir assets/i18n lib/services/localization.dart
node bin/splitLocales
flutter pub pub run bin/split_locales.dart
rm assets/i18n/intl_messages.arb

build_locale:
node bin/buildLocales
flutter pub pub run bin/build_locales.dart
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/locale --no-use-deferred-loading lib/services/localization.dart assets/i18n/intl_*.arb
23 changes: 15 additions & 8 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Expand All @@ -26,7 +26,9 @@
<application
android:name="io.flutter.app.FlutterApplication"
android:label="Okuna"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"
>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
Expand Down Expand Up @@ -65,14 +67,19 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
<activity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.*;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;

public class ImageConverter {
public enum TargetFormat {
Expand All @@ -27,8 +28,4 @@ public static byte[] convertImageData(InputStream imageData, TargetFormat format

return outputStream.toByteArray();
}

public static byte[] convertImageDataFile(File file, TargetFormat format) throws FileNotFoundException {
return convertImageData(new FileInputStream(file), format);
}
}
198 changes: 173 additions & 25 deletions android/app/src/main/java/com/example/openbook/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,31 @@
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;

import com.example.openbook.ImageConverter;
import com.example.openbook.plugins.ImageConverterPlugin;
import com.example.openbook.util.InputStreamSupplier;

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

import com.example.openbook.plugins.ImageConverterPlugin;

public class MainActivity extends FlutterActivity {

public static final String SHARE_STREAM = "openbook.social/receive_share";
Expand Down Expand Up @@ -74,47 +82,187 @@ private void sendIntent(Intent intent) {
}

Map<String, String> args = new HashMap<>();
if (intent.getType().startsWith("image/")) {
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
uri = copyImageToTempFile(uri);
args.put("path", uri.toString());
} else if (intent.getType().startsWith("text/")) {
args.put("text", intent.getStringExtra(Intent.EXTRA_TEXT));
} else {
Log.w(getClass().getSimpleName(), "unknown intent type \"" + intent.getType() + "\" received, ignoring");
return;

try {
if (intent.getType().startsWith("image/")) {
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (!getExtensionFromUri(uri).equalsIgnoreCase("gif")) {
args.put("image", copyImageToTempFile(uri).toString());
} else {
args.put("video", copyVideoToTempFileIfNeeded(uri).toString());
}
} else if (intent.getType().startsWith("video/")) {
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
args.put("video", copyVideoToTempFileIfNeeded(uri).toString());
} else if (intent.getType().startsWith("text/")) {
args.put("text", intent.getStringExtra(Intent.EXTRA_TEXT));
} else {
Log.w(getClass().getSimpleName(), "unknown intent type \"" + intent.getType() + "\" received, ignoring");
return;
}
} catch (KeyedException e) {
String msg = String.format("an exception occurred while receiving share of type %s" +
"%n %s", intent.getType(), e.getCause() != null ? e.getCause().toString() : e.toString());
String errorTextKey = getLocalizationKey(e);

args.put("error", errorTextKey);
Log.w(getClass().getSimpleName(), msg);
}

Log.i(getClass().getSimpleName(), "sending intent to flutter");
eventSink.success(args);
}
}

private Uri copyImageToTempFile(Uri imageUri) {
private Uri copyImageToTempFile(Uri imageUri) throws KeyedException {
byte[] data = convertImage(imageUri);
File imageFile = createTemporaryFile(".jpeg");
copyResourceToFile(() -> new ByteArrayInputStream(data), imageFile);

return Uri.fromFile(imageFile);
}

private byte[] convertImage(Uri imageUri) throws KeyedException {
try {
byte[] data;
InputStream imageStream;

if (imageUri.getScheme().equals("content")) {
data = ImageConverter.convertImageData(this.getContentResolver().openInputStream(imageUri), ImageConverter.TargetFormat.JPEG);
imageStream = this.getContentResolver().openInputStream(imageUri);
} else if (imageUri.getScheme().equals("file")) {
imageStream = new FileInputStream(imageUri.getPath());
} else {
data = ImageConverter.convertImageDataFile(new File(imageUri.getPath()), ImageConverter.TargetFormat.JPEG);
throw new KeyedException(KeyedException.Key.UriSchemeNotSupported, imageUri.getScheme(), null);
}

File imageFile = createTemporaryFile(".jpeg");
FileOutputStream fileOutput = new FileOutputStream(imageFile);
fileOutput.write(data);
fileOutput.close();
return ImageConverter.convertImageData(imageStream, ImageConverter.TargetFormat.JPEG);
} catch (FileNotFoundException e) {
throw new KeyedException(KeyedException.Key.ReadFileMissing, e);
}
}

return Uri.fromFile(imageFile);
} catch (IOException e) {
throw new RuntimeException(e);
private Uri copyVideoToTempFileIfNeeded(Uri videoUri) throws KeyedException {
Uri result = null;

if (videoUri.getScheme().equals("file")) {
result = videoUri;
} else if (videoUri.getScheme().equals("content")){
String extension = getExtensionFromUri(videoUri);
File tempFile = createTemporaryFile("." + extension);
copyResourceToFile(() -> getContentResolver().openInputStream(videoUri), tempFile);
result = Uri.fromFile(tempFile);
} else {
throw new KeyedException(KeyedException.Key.UriSchemeNotSupported, videoUri.getScheme(), null);
}

return result;
}

private File createTemporaryFile(String extension) {
private String getExtensionFromUri(Uri uri) throws KeyedException {
if (uri.getScheme().equals("content")) {
String mime = this.getContentResolver().getType(uri);
return MimeTypeMap.getSingleton().getExtensionFromMimeType(mime);
} else if (uri.getScheme().equals("file")) {
return MimeTypeMap.getFileExtensionFromUrl(uri.toString());
} else {
throw new KeyedException(KeyedException.Key.UriSchemeNotSupported, uri.getScheme(), null);
}
}

private File createTemporaryFile(String extension) throws KeyedException {
String name = UUID.randomUUID().toString();

try {
String name = UUID.randomUUID().toString();
return File.createTempFile(name, extension, this.getExternalFilesDir(Environment.DIRECTORY_PICTURES));
} catch (IOException e) {
throw new RuntimeException(e);
throw new KeyedException(KeyedException.Key.TempCreationFailed, e);
} catch (SecurityException e) {
throw new KeyedException(KeyedException.Key.TempCreationDenied, e);
}
}

private void copyResourceToFile(InputStreamSupplier inputSupplier, File target) throws KeyedException {
try (InputStream input = inputSupplier.get()) {
try (OutputStream output = new FileOutputStream(target)) {
byte[] data = new byte[1024];
int length;
while ((length = input.read(data)) > 0) {
output.write(data, 0, length);
}
}
catch (FileNotFoundException e) {
throw new KeyedException(KeyedException.Key.WriteTempMissing, e);
} catch (IOException e) {
throw new KeyedException(KeyedException.Key.WriteTempFailed, e);
} catch (SecurityException e) {
throw new KeyedException(KeyedException.Key.WriteTempDenied, e);
}
}
catch (FileNotFoundException e) {
throw new KeyedException(KeyedException.Key.ReadFileMissing, e);
} catch (IOException e) {
//Exception when closing the streams. Ignore.
}
}

private String getLocalizationKey(KeyedException e) {
String errorTextKey = "";

switch (e.getKey()) {
case TempCreationFailed:
case WriteTempFailed:
case WriteTempMissing:
errorTextKey = "error__receive_share_temp_write_failed";
break;
case WriteTempDenied:
case TempCreationDenied:
errorTextKey = "error__receive_share_temp_write_denied";
break;
case UriSchemeNotSupported:
errorTextKey = "error__receive_share_invalid_uri_scheme";
break;
case ReadFileMissing:
errorTextKey = "error__receive_share_file_not_found";
break;
}

return errorTextKey;
}
}

class KeyedException extends Exception {
public enum Key {
TempCreationFailed("Failed to create temporary file."),
TempCreationDenied(TempCreationFailed.message),
WriteTempDenied("Failed to write to temporary file."),
WriteTempFailed(WriteTempDenied.message),
WriteTempMissing(WriteTempDenied.message),
ReadFileMissing("Failed to read the shared file."),
UriSchemeNotSupported("Unsupported UR scheme: ");

private String message;

private Key(String msg) {
message = msg;
}
}
private final Key key;

public KeyedException(Key key, Throwable cause) {
super(cause);
this.key = key;
}

public KeyedException(Key key, String message, Throwable cause) {
super(message, cause);
this.key = key;
}

public Key getKey() {
return key;
}

@Override
public String getMessage() {
return key.message + super.getMessage();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.openbook.util;

import java.io.FileNotFoundException;
import java.io.InputStream;

@FunctionalInterface
public interface InputStreamSupplier {
public InputStream get() throws FileNotFoundException;
}
5 changes: 5 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}

ext {
flutterFFmpegPackage = "full-gpl-lts"
}

subprojects {
project.evaluationDependsOn(':app')
}
Expand Down
Loading

0 comments on commit 682655d

Please sign in to comment.