Skip to content

Commit

Permalink
fix(android): allow TiDownloadManager to fire fail listener (#11575)
Browse files Browse the repository at this point in the history
throw exception from background thread

Fixes TIMOB-27797
  • Loading branch information
garymathews committed Apr 28, 2020
1 parent b91f335 commit 68d11f7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*/
package org.appcelerator.titanium.util;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor;
Expand All @@ -18,18 +21,13 @@
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.kroll.util.KrollStreamHelper;
import org.appcelerator.titanium.io.TiInputStreamWrapper;
import org.appcelerator.titanium.TiApplication;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import org.appcelerator.titanium.io.TiInputStreamWrapper;

/**
* Manages the asynchronous opening of InputStreams from URIs so that
Expand Down Expand Up @@ -86,9 +84,9 @@ public void download(URI uri, TiDownloadListener listener)
* @return
* Returns a stream to the file/content being downloaded.
* <p>
* Returns null if failed to download content or if given an invalid argument.
* Throws exception if failed to download content.
*/
public InputStream blockingDownload(final URI uri)
public InputStream blockingDownload(final URI uri) throws Exception
{
// Validate.
if (uri == null) {
Expand All @@ -113,46 +111,36 @@ public InputStream blockingDownload(final URI uri)
// Note: Using "HttpUrlConnection" on UI thread will cause a "NetworkOnMainThreadException" to be thrown.
if (TiApplication.isUIThread()) {
// Perform the blocking download on another thread.
// Downloaded content will be made available via Titanium's "TiResponseCache".
try {
Thread thread = new Thread(new Runnable() {
@Override
public void run()
{
try (InputStream stream = blockingDownload(uri)) {
if (stream != null) {
KrollStreamHelper.pump(stream, null);
}
} catch (Exception ex) {
Log.e(TAG, "Exception downloading from: " + uri.toString(), ex);
}
// Downloaded content will be made available via Titanium's "TiResponseCache"
AtomicReference<Exception> exception = new AtomicReference<>(null);
Thread thread = new Thread(() -> {
try (InputStream stream = blockingDownload(uri)) {
if (stream != null) {
KrollStreamHelper.pump(stream, null);
}
});
thread.start();
thread.join();
} catch (Exception ex) {
} catch (Exception ex) {
exception.set(ex);
}
});
thread.start();
thread.join();

// Handle download thread exception.
if (exception.get() != null) {
throw exception.get();
}

// Return a stream to the downloaded file/content via our response cache.
URI cachedUri = TiResponseCache.fetchEndpointFollowingRedirects(uri);
if (cachedUri != null) {
try {
inputStream = TiResponseCache.openCachedStream(cachedUri);
} catch (Exception ex) {
}
inputStream = TiResponseCache.openCachedStream(cachedUri);
}
return inputStream;
}

// Convert the given URI to a URL object.
// Note: This object will validate the string and throw an exception if malformed.
URL url = null;
try {
url = new URL(uri.toString());
} catch (Exception ex) {
Log.e(TAG, "Failed to parse URL: " + uri.toString(), ex);
return null;
}
URL url = new URL(uri.toString());

// Attempt to download the file.
URLConnection connection = null;
Expand Down Expand Up @@ -215,9 +203,6 @@ public void run()
}
break;
}
} catch (Exception ex) {
// Failed to download file/content.
Log.e(TAG, "Failed to download from: " + uri.toString(), ex);
} finally {
// Close the connection if we don't have a stream to the response body. (Nothing to download.)
if ((inputStream == null) && (connection instanceof HttpURLConnection)) {
Expand Down Expand Up @@ -356,7 +341,7 @@ public void run()

// fire a download fail event if we are unable to download
sendMessage(uri, MSG_FIRE_DOWNLOAD_FAILED);
Log.e(TAG, "Exception downloading from: " + uri, e);
Log.e(TAG, "Exception downloading from: " + uri + "\n" + e.getMessage());
}
}
}
Expand Down
55 changes: 55 additions & 0 deletions tests/Resources/ti.ui.imageview.addontest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Appcelerator Titanium Mobile
* Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* eslint-env mocha */
/* eslint no-unused-expressions: "off" */
'use strict';

describe('Titanium.UI.ImageView', function () {
var win;
this.timeout(5000);

afterEach(function (done) {
if (win) {
// If `win` is already closed, we're done.
let t = setTimeout(function () {
if (win) {
win = null;
done();
}
}, 3000);

win.addEventListener('close', function listener () {
clearTimeout(t);

if (win) {
win.removeEventListener('close', listener);
}
win = null;
done();
});
win.close();
} else {
win = null;
done();
}
});

it('image error event', function (finish) {
win = Ti.UI.createWindow();

const img = Ti.UI.createImageView({
image: 'https://invalid.host.com/image.jpg'
});

img.addEventListener('error', () => {
finish();
});

win.add(img);
win.open();
});
});

0 comments on commit 68d11f7

Please sign in to comment.