Android Open Source - Android-Print-SDK Asset Upload Request






From Project

Back to project page Android-Print-SDK.

License

The source code is released under:

MIT License

If you think the Android project Android-Print-SDK listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package ly.kite.print;
/*w  w w  . java  2  s.  c  om*/
import android.content.Context;
import android.os.AsyncTask;
import android.os.Looper;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by deonbotha on 07/02/2014.
 */
class AssetUploadRequest {

    private boolean cancelled;
    private BaseRequest registerImageURLAssetsReq, signReq;
    private int numOutstandingAsyncOpertions = 0;
    private boolean notifiedUploadListenerOfOutcome = false;

    public void cancelUpload() {
        cancelled = true;
        notifiedUploadListenerOfOutcome = false;
        numOutstandingAsyncOpertions = 0;
        if (registerImageURLAssetsReq != null) {
            registerImageURLAssetsReq.cancel();
            registerImageURLAssetsReq = null;
        }

        if (signReq != null) {
            signReq.cancel();
            signReq = null;
        }
    }

    public void uploadAsset(Asset asset, Context context, AssetUploadRequestListener uploadListener) {
        ArrayList<Asset> list = new ArrayList<Asset>();
        list.add(asset);
        uploadAssets(list, context, uploadListener);
    }

    public void uploadAssets(final List<Asset> assets, Context context, final AssetUploadRequestListener uploadListener) {
        ArrayList<Asset> urlsToRegister = new ArrayList<Asset>();
        ArrayList<Asset> assetsToUpload = new ArrayList<Asset>();

        for (Asset asset : assets) {
            if (asset.getType() == Asset.AssetType.REMOTE_URL) {
                urlsToRegister.add(asset);
            } else {
                assetsToUpload.add(asset);
            }
        }

        final AssetUploadOrRegisterListener listener = new AssetUploadOrRegisterListener() {
            @Override
            public void onProgress(int totalAssetsUploaded, int totalAssetsToUpload, long bytesWritten, long totalAssetBytesWritten, long totalAssetBytesExpectedToWrite) {
                if (cancelled || notifiedUploadListenerOfOutcome) return;
                uploadListener.onProgress(AssetUploadRequest.this, totalAssetsUploaded, totalAssetsToUpload, bytesWritten, totalAssetBytesWritten, totalAssetBytesExpectedToWrite);
            }

            @Override
            public void onSuccess() {
                if (cancelled || notifiedUploadListenerOfOutcome) return;
                completedOutstandingAsyncOperation(assets, null, uploadListener);
            }

            @Override
            public void onError(Exception ex) {
                if (cancelled || notifiedUploadListenerOfOutcome) return;
                completedOutstandingAsyncOperation(assets, ex, uploadListener);
            }
        };

        if (assetsToUpload.size() > 0) {
            ++numOutstandingAsyncOpertions;
            uploadAssets(assetsToUpload, context, listener);
        }

        if (urlsToRegister.size() > 0) {
            ++numOutstandingAsyncOpertions;
            registerImageURLs(urlsToRegister, context, listener);
        }
    }

    private void completedOutstandingAsyncOperation(List<Asset> assets, Exception ex, AssetUploadRequestListener listener) {
        if (cancelled || notifiedUploadListenerOfOutcome) {
            return;
        }

        if (ex != null) {
            notifiedUploadListenerOfOutcome = true;
            listener.onError(this, ex);
            return;
        }

        if (--numOutstandingAsyncOpertions == 0) {
            notifiedUploadListenerOfOutcome = true;
            assert ex == null : "errors should be covered above";
            listener.onUploadComplete(this, assets);
        }
    }

    private void getSignedS3UploadRequestURLs(final List<Asset> assets, Context context, final SignS3UploadsRequestListener listener) {
        StringBuilder mimeTypes = new StringBuilder();
        for (Asset a : assets) {
            if (mimeTypes.length() > 0) {
                mimeTypes.append(",");
            }

            mimeTypes.append(a.getMimeType(context).getMimeTypeString());
        }

        String url = String.format("%s/v1/asset/sign/?mime_types=%s&client_asset=true", KitePrintSDK.getEnvironment().getPrintAPIEndpoint(), mimeTypes.toString());
        registerImageURLAssetsReq = new BaseRequest(BaseRequest.HttpMethod.GET, url, null, (String) null);
        registerImageURLAssetsReq.start(new BaseRequest.BaseRequestListener() {
            @Override
            public void onSuccess(int httpStatusCode, JSONObject json) {
                if (cancelled || notifiedUploadListenerOfOutcome) return;

                try {
                    if (httpStatusCode != 200) {
                        JSONObject error = json.getJSONObject("error");
                        String message = error.getString("message");
                        listener.onError(new IllegalStateException(message));
                        return;
                    }

                    JSONArray signedUploadReqURLs = json.getJSONArray("signed_requests");
                    JSONArray assetS3PreviewURLs = json.getJSONArray("urls");
                    JSONArray assetIds = json.getJSONArray("asset_ids");

                    if (assets.size() != signedUploadReqURLs.length() || signedUploadReqURLs.length() != assetS3PreviewURLs.length() || assetS3PreviewURLs.length() != assetIds.length()) {
                        listener.onError(new IllegalStateException(String.format("Only got sign %d/%d sign requests", signedUploadReqURLs.length(), assets.size())));
                        return;
                    }

                    ArrayList<SignedS3RequestUploadDetails> details = new ArrayList<SignedS3RequestUploadDetails>();
                    for (int i = 0; i < signedUploadReqURLs.length(); ++i) {
                        SignedS3RequestUploadDetails d = new SignedS3RequestUploadDetails();
                        d.signedS3UploadReqURL = new URL(signedUploadReqURLs.getString(i));
                        d.s3AssetPreviewURL = new URL(assetS3PreviewURLs.getString(i));
                        d.assetId = assetIds.getLong(i);
                        d.asset = assets.get(i);
                        details.add(d);
                    }

                    listener.onSuccess(details);
                } catch (Exception ex) {
                    listener.onError(ex);
                }
            }

            @Override
            public void onError(Exception ex) {
                listener.onError(ex);
            }
        });
    }

    private void uploadAssetToS3(Context context, final SignedS3RequestUploadDetails details, final byte[] bytes, final UploadToS3Listener listener) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            throw new IllegalStateException("Attempting to kick off asset upload on a thread that is not the main thread");
        }

        final String mimeType = details.asset.getMimeType(context).getMimeTypeString();
        AsyncTask<Void, Void, Exception> uploadTask = new AsyncTask<Void, Void, Exception>() {
            @Override
            protected Exception doInBackground(Void... voids) {
                HttpClient httpclient = new DefaultHttpClient();
                HttpPut request = new HttpPut(details.signedS3UploadReqURL.toString());
                request.setHeader("Content-Type", mimeType);
                request.setHeader("x-amz-acl", "public-read");
                request.setEntity(new ByteArrayEntity(bytes));

                try {
                    HttpResponse response = httpclient.execute(request);
                    int statusCode = response.getStatusLine().getStatusCode();
                    if (statusCode >= 200 && statusCode <= 299) {
                        return null;
                    } else {
                        return new IllegalStateException("Failed to upload asset to amazon s3 with status code: " + statusCode);
                    }
                } catch (Exception e) {
                    return e;
                }
            }

            @Override
            protected void onPostExecute(Exception ex) {
                if (ex != null) {
                    listener.onError(ex);
                } else {
                    listener.onProgress(bytes.length, bytes.length, bytes.length); // TODO: do proper upload progress tracking rather than one off callback on completion
                    listener.onUploadComplete();
                }
            }
        };

        uploadTask.execute();
    }

    private void uploadAssetsToS3(final List<SignedS3RequestUploadDetails> remainingAssetsToUpload, final List<Asset> uploadedAssetAccumulator, final Context context, final AssetUploadOrRegisterListener listener) {
        if (cancelled || notifiedUploadListenerOfOutcome) return;

        final SignedS3RequestUploadDetails assetToUploadDetails = remainingAssetsToUpload.remove(0);
        final int totalAssetsToUpload = uploadedAssetAccumulator.size() + remainingAssetsToUpload.size() + 1;
        assetToUploadDetails.asset.getBytes(context, new AssetGetBytesListener() {
            @Override
            public void onBytes(Asset asset, byte[] bytes) {
                if (cancelled || notifiedUploadListenerOfOutcome) return;

                listener.onProgress(uploadedAssetAccumulator.size(), totalAssetsToUpload, 0, 0, bytes.length);
                uploadAssetToS3(context, assetToUploadDetails, bytes, new UploadToS3Listener() {
                    @Override
                    public void onProgress(long bytesWritten, long totalAssetBytesWritten, long totalAssetBytesExpectedToWrite) {
                        if (cancelled || notifiedUploadListenerOfOutcome) return;
                        listener.onProgress(uploadedAssetAccumulator.size(), totalAssetsToUpload, bytesWritten, totalAssetBytesWritten, totalAssetBytesExpectedToWrite);
                    }

                    @Override
                    public void onUploadComplete() {
                        if (cancelled || notifiedUploadListenerOfOutcome) return;

                        Asset asset = assetToUploadDetails.asset;
                        asset.markAsUploaded(assetToUploadDetails.assetId, assetToUploadDetails.s3AssetPreviewURL);
                        uploadedAssetAccumulator.add(asset);
                        if (remainingAssetsToUpload.size() == 0) {
                            listener.onSuccess();
                        } else {
                            uploadAssetsToS3(remainingAssetsToUpload, uploadedAssetAccumulator, context, listener);
                        }
                    }

                    @Override
                    public void onError(Exception ex) {
                        if (cancelled || notifiedUploadListenerOfOutcome) return;
                        listener.onError(ex);
                    }
                });
            }

            @Override
            public void onError(Asset asset, Exception ex) {
                if (cancelled || notifiedUploadListenerOfOutcome) return;
                listener.onError(ex);
            }
        });
    }

    private void uploadAssets(final List<Asset> assets, final Context context, final AssetUploadOrRegisterListener listener) {
        getSignedS3UploadRequestURLs(assets, context, new SignS3UploadsRequestListener() {

            @Override
            public void onSuccess(ArrayList<SignedS3RequestUploadDetails> details) {
                uploadAssetsToS3(details, new ArrayList<Asset>(), context, listener);
            }

            @Override
            public void onError(Exception ex) {
                listener.onError(ex);
            }
        });
    }

    private void registerImageURLs(final List<Asset> assets, Context context, final AssetUploadOrRegisterListener listener) {
        int c = 0;
        JSONObject jsonBody = new JSONObject();
        JSONArray objects = new JSONArray();
        try {
            jsonBody.put("objects", objects);
            for (Asset asset : assets) {
                if (asset.getType() == Asset.AssetType.REMOTE_URL) {
                    ++c;
                    JSONObject o = new JSONObject();
                    o.put("url", asset.getRemoteURL().toString());
                    o.put("client_asset", true);
                    o.put("mime_type", asset.getMimeType(context).getMimeTypeString());
                    objects.put(o);
                }
            }
        } catch (JSONException ex) {
            listener.onError(ex);
            return;
        }

        final int expectedRegisteredAssetCount = c;

        String url = String.format("%s/v1/asset/", KitePrintSDK.getEnvironment().getPrintAPIEndpoint());
        registerImageURLAssetsReq = new BaseRequest(BaseRequest.HttpMethod.PATCH, url, null, jsonBody.toString());
        registerImageURLAssetsReq.start(new BaseRequest.BaseRequestListener() {
            @Override
            public void onSuccess(int httpStatusCode, JSONObject json) {
                int registeredAssetCount = 0;
                try {
                    if (httpStatusCode >= 200 && httpStatusCode <= 299) {
                        JSONArray objects = json.getJSONArray("objects");
                        for (int i = 0; i < objects.length(); ++i) {
                            JSONObject o = objects.getJSONObject(i);
                            long assetId = o.getLong("asset_id");
                            URL previewURL = new URL(o.getString("url"));

                            for (Asset asset : assets) {
                                if (asset.getType() == Asset.AssetType.REMOTE_URL && asset.getRemoteURL().equals(previewURL)) {
                                    asset.markAsUploaded(assetId, previewURL);
                                    ++registeredAssetCount;
                                }
                            }
                        }

                        if (registeredAssetCount == expectedRegisteredAssetCount) {
                            listener.onSuccess();
                        } else {
                            listener.onError(new IllegalStateException(String.format("Only registered %d/%d image URLs with the asset endpoint", registeredAssetCount, expectedRegisteredAssetCount)));
                        }
                    } else {
                        JSONObject error = json.getJSONObject("error");
                        String message = error.getString("message");
                        listener.onError(new IllegalStateException(message));
                    }
                } catch (Exception ex) {
                    listener.onError(ex);
                }
            }

            @Override
            public void onError(Exception ex) {
                listener.onError(ex);
            }
        });
    }

    private static class SignedS3RequestUploadDetails {
        URL signedS3UploadReqURL;
        URL s3AssetPreviewURL;
        long assetId;
        Asset asset;
    }

    private static interface AssetUploadOrRegisterListener {
        void onProgress(int totalAssetsUploaded, int totalAssetsToUpload, long bytesWritten, long totalAssetBytesWritten, long totalAssetBytesExpectedToWrite);
        void onSuccess();
        void onError(Exception ex);
    }

    private static interface SignS3UploadsRequestListener {
        void onSuccess(ArrayList<SignedS3RequestUploadDetails> details);
        void onError(Exception ex);
    }

    private static interface UploadToS3Listener {
        void onProgress(long bytesWritten, long totalAssetBytesWritten, long totalAssetBytesExpectedToWrite);
        void onUploadComplete();
        void onError(Exception ex);
    }
}




Java Source Code List

co.oceanlabs.sample.MainActivity.java
ly.kite.address.AddressBookActivity.java
ly.kite.address.AddressEditActivity.java
ly.kite.address.AddressSearchActivity.java
ly.kite.address.AddressSearchRequestListener.java
ly.kite.address.AddressSearchRequest.java
ly.kite.address.Address.java
ly.kite.address.Country.java
ly.kite.checkout.CheckoutActivity.java
ly.kite.checkout.OrderReceiptActivity.java
ly.kite.checkout.PaymentActivity.java
ly.kite.checkout.PrintOrderSummaryListAdapter.java
ly.kite.payment.CheckPromoCodeRequestListener.java
ly.kite.payment.CheckPromoRequest.java
ly.kite.payment.PayPalCardChargeListener.java
ly.kite.payment.PayPalCardVaultStorageListener.java
ly.kite.payment.PayPalCard.java
ly.kite.print.ApplyPromoCodeListener.java
ly.kite.print.AssetGetBytesLengthListener.java
ly.kite.print.AssetGetBytesListener.java
ly.kite.print.AssetUploadRequestListener.java
ly.kite.print.AssetUploadRequest.java
ly.kite.print.Asset.java
ly.kite.print.BaseRequest.java
ly.kite.print.KitePrintSDKException.java
ly.kite.print.KitePrintSDK.java
ly.kite.print.PrintJob.java
ly.kite.print.PrintOrderSubmissionListener.java
ly.kite.print.PrintOrder.java
ly.kite.print.PrintsPrintJob.java
ly.kite.print.ProductType.java
ly.kite.print.SubmitPrintOrderRequestListener.java
ly.kite.print.SubmitPrintOrderRequest.java