Commit 4f4147d0 by Sebastián Katzer

Fixes #588 crash when basename & extension can't be extracted

parent 52054f5d
...@@ -5,6 +5,7 @@ Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-lo ...@@ -5,6 +5,7 @@ Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-lo
#### Version 0.8.3 (not yet released) #### Version 0.8.3 (not yet released)
- New "quarter" intervall for iOS & Android - New "quarter" intervall for iOS & Android
- Fixed #588 crash when basename & extension can't be extracted (Android)
- Fixed #732 loop between update and trigger (Android) - Fixed #732 loop between update and trigger (Android)
- Fixed #710 crash due to >500 notifications (Android) - Fixed #710 crash due to >500 notifications (Android)
- Fixed #682 crash while resuming app from notification (Android 6) - Fixed #682 crash while resuming app from notification (Android 6)
......
...@@ -42,6 +42,7 @@ import java.io.OutputStream; ...@@ -42,6 +42,7 @@ import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.UUID;
/** /**
* Util class to map unified asset URIs to native URIs. URIs like file:/// * Util class to map unified asset URIs to native URIs. URIs like file:///
...@@ -61,15 +62,15 @@ class AssetUtil { ...@@ -61,15 +62,15 @@ class AssetUtil {
// resources and app directory. // resources and app directory.
private final Context context; private final Context context;
/** /**
* Constructor * Constructor
* *
* @param context * @param context
* Application context * Application context
*/ */
private AssetUtil(Context context) { private AssetUtil(Context context) {
this.context = context; this.context = context;
} }
/** /**
* Static method to retrieve class instance. * Static method to retrieve class instance.
...@@ -100,223 +101,199 @@ class AssetUtil { ...@@ -100,223 +101,199 @@ class AssetUtil {
return parse(path); return parse(path);
} }
/** /**
* The URI for a path. * The URI for a path.
* *
* @param path * @param path
* The given path * The given path
*/ */
Uri parse (String path) { Uri parse (String path) {
if (path.startsWith("res:")) { if (path.startsWith("res:")) {
return getUriForResourcePath(path); return getUriForResourcePath(path);
} else if (path.startsWith("file:///")) { } else if (path.startsWith("file:///")) {
return getUriFromPath(path); return getUriFromPath(path);
} else if (path.startsWith("file://")) { } else if (path.startsWith("file://")) {
return getUriFromAsset(path); return getUriFromAsset(path);
} else if (path.startsWith("http")){ } else if (path.startsWith("http")){
return getUriFromRemote(path); return getUriFromRemote(path);
} }
return Uri.EMPTY; return Uri.EMPTY;
} }
/** /**
* URI for a file. * URI for a file.
* *
* @param path * @param path
* Absolute path like file:///... * Absolute path like file:///...
* *
* @return * @return
* URI pointing to the given path
*/
private Uri getUriFromPath(String path) {
String absPath = path.replaceFirst("file://", "");
File file = new File(absPath);
if (!file.exists()) {
Log.e("Asset", "File not found: " + file.getAbsolutePath());
return Uri.EMPTY;
}
return Uri.fromFile(file);
}
/**
* URI for an asset.
*
* @param path
* Asset path like file://...
*
* @return
* URI pointing to the given path * URI pointing to the given path
*/ */
private Uri getUriFromAsset(String path) { private Uri getUriFromPath(String path) {
File dir = context.getExternalCacheDir(); String absPath = path.replaceFirst("file://", "");
File file = new File(absPath);
if (!file.exists()) {
Log.e("Asset", "File not found: " + file.getAbsolutePath());
return Uri.EMPTY;
}
if (dir == null) { return Uri.fromFile(file);
Log.e("Asset", "Missing external cache dir"); }
return Uri.EMPTY;
}
/**
* URI for an asset.
*
* @param path
* Asset path like file://...
*
* @return
* URI pointing to the given path
*/
private Uri getUriFromAsset(String path) {
String resPath = path.replaceFirst("file:/", "www"); String resPath = path.replaceFirst("file:/", "www");
String fileName = resPath.substring(resPath.lastIndexOf('/') + 1); String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
String storage = dir.toString() + STORAGE_FOLDER; File file = getTmpFile(fileName);
File file = new File(storage, fileName);
//noinspection ResultOfMethodCallIgnored if (file == null) {
new File(storage).mkdir(); Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
try { try {
AssetManager assets = context.getAssets(); AssetManager assets = context.getAssets();
FileOutputStream outStream = new FileOutputStream(file); FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = assets.open(resPath); InputStream inputStream = assets.open(resPath);
copyFile(inputStream, outStream); copyFile(inputStream, outStream);
outStream.flush(); outStream.flush();
outStream.close(); outStream.close();
return Uri.fromFile(file); return Uri.fromFile(file);
} catch (Exception e) { } catch (Exception e) {
Log.e("Asset", "File not found: assets/" + resPath); Log.e("Asset", "File not found: assets/" + resPath);
e.printStackTrace(); e.printStackTrace();
} }
return Uri.EMPTY; return Uri.EMPTY;
} }
/** /**
* The URI for a resource. * The URI for a resource.
* *
* @param path * @param path
* The given relative path * The given relative path
* *
* @return * @return
* URI pointing to the given path * URI pointing to the given path
*/ */
private Uri getUriForResourcePath(String path) { private Uri getUriForResourcePath(String path) {
File dir = context.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
String resPath = path.replaceFirst("res://", ""); String resPath = path.replaceFirst("res://", "");
int resId = getResIdForDrawable(resPath);
File file = getTmpFile();
int resId = getResIdForDrawable(resPath); if (resId == 0) {
Log.e("Asset", "File not found: " + resPath);
if (resId == 0) { return Uri.EMPTY;
Log.e("Asset", "File not found: " + resPath); }
return Uri.EMPTY;
}
String resName = extractResourceName(resPath);
String extName = extractResourceExtension(resPath);
String storage = dir.toString() + STORAGE_FOLDER;
File file = new File(storage, resName + extName);
//noinspection ResultOfMethodCallIgnored if (file == null) {
new File(storage).mkdir(); Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
try { try {
Resources res = context.getResources(); Resources res = context.getResources();
FileOutputStream outStream = new FileOutputStream(file); FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = res.openRawResource(resId); InputStream inputStream = res.openRawResource(resId);
copyFile(inputStream, outStream); copyFile(inputStream, outStream);
outStream.flush(); outStream.flush();
outStream.close(); outStream.close();
return Uri.fromFile(file); return Uri.fromFile(file);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return Uri.EMPTY; return Uri.EMPTY;
} }
/** /**
* Uri from remote located content. * Uri from remote located content.
* *
* @param path * @param path
* Remote address * Remote address
* *
* @return * @return
* Uri of the downloaded file * Uri of the downloaded file
*/ */
private Uri getUriFromRemote(String path) { private Uri getUriFromRemote(String path) {
File dir = context.getExternalCacheDir(); File file = getTmpFile();
if (dir == null) { if (file == null) {
Log.e("Asset", "Missing external cache dir"); Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY; return Uri.EMPTY;
} }
String resName = extractResourceName(path);
String extName = extractResourceExtension(path);
String storage = dir.toString() + STORAGE_FOLDER;
File file = new File(storage, resName + extName);
//noinspection ResultOfMethodCallIgnored
new File(storage).mkdir();
try { try {
URL url = new URL(path); URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
StrictMode.ThreadPolicy policy = StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build(); new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy); StrictMode.setThreadPolicy(policy);
connection.setRequestProperty("Connection", "close"); connection.setRequestProperty("Connection", "close");
connection.setConnectTimeout(5000); connection.setConnectTimeout(5000);
connection.connect(); connection.connect();
InputStream input = connection.getInputStream(); InputStream input = connection.getInputStream();
FileOutputStream outStream = new FileOutputStream(file); FileOutputStream outStream = new FileOutputStream(file);
copyFile(input, outStream); copyFile(input, outStream);
outStream.flush(); outStream.flush();
outStream.close(); outStream.close();
return Uri.fromFile(file); return Uri.fromFile(file);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
Log.e("Asset", "Incorrect URL"); Log.e("Asset", "Incorrect URL");
e.printStackTrace(); e.printStackTrace();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Log.e("Asset", "Failed to create new File from HTTP Content"); Log.e("Asset", "Failed to create new File from HTTP Content");
e.printStackTrace(); e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
Log.e("Asset", "No Input can be created from http Stream"); Log.e("Asset", "No Input can be created from http Stream");
e.printStackTrace(); e.printStackTrace();
} }
return Uri.EMPTY; return Uri.EMPTY;
} }
/** /**
* Copy content from input stream into output stream. * Copy content from input stream into output stream.
* *
* @param in * @param in
* The input stream * The input stream
* @param out * @param out
* The output stream * The output stream
*/ */
private void copyFile(InputStream in, OutputStream out) throws IOException { private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
int read; int read;
while ((read = in.read(buffer)) != -1) { while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read); out.write(buffer, 0, read);
} }
} }
/** /**
* Resource ID for drawable. * Resource ID for drawable.
...@@ -343,7 +320,7 @@ class AssetUtil { ...@@ -343,7 +320,7 @@ class AssetUtil {
* Resource path as string * Resource path as string
*/ */
int getResIdForDrawable(String clsName, String resPath) { int getResIdForDrawable(String clsName, String resPath) {
String drawable = extractResourceName(resPath); String drawable = getBaseName(resPath);
int resId = 0; int resId = 0;
try { try {
...@@ -396,7 +373,7 @@ class AssetUtil { ...@@ -396,7 +373,7 @@ class AssetUtil {
* @param resPath * @param resPath
* Resource path as string * Resource path as string
*/ */
private String extractResourceName (String resPath) { private String getBaseName (String resPath) {
String drawable = resPath; String drawable = resPath;
if (drawable.contains("/")) { if (drawable.contains("/")) {
...@@ -411,19 +388,39 @@ class AssetUtil { ...@@ -411,19 +388,39 @@ class AssetUtil {
} }
/** /**
* Extract extension of drawable resource from path. * Returns a file located under the external cache dir of that app.
* *
* @param resPath * @return
* Resource path as string * File with a random UUID name
*/ */
private String extractResourceExtension (String resPath) { private File getTmpFile () {
String extName = "png"; // If random UUID is not be enough see
// https://github.com/LukePulverenti/cordova-plugin-local-notifications/blob/267170db14044cbeff6f4c3c62d9b766b7a1dd62/src/android/notification/AssetUtil.java#L255
return getTmpFile(UUID.randomUUID().toString());
}
if (resPath.contains(".")) { /**
extName = resPath.substring(resPath.lastIndexOf('.')); * Returns a file located under the external cache dir of that app.
*
* @param name
* The name of the file
* @return
* File with the provided name
*/
private File getTmpFile (String name) {
File dir = context.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return null;
} }
return extName; String storage = dir.toString() + STORAGE_FOLDER;
//noinspection ResultOfMethodCallIgnored
new File(storage).mkdir();
return new File(storage, name);
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment