ac.robinson.paperchains.SoundCloudUploadTask.java Source code

Java tutorial

Introduction

Here is the source code for ac.robinson.paperchains.SoundCloudUploadTask.java

Source

/*
 * Copyright (c) 2014 Simon Robinson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ac.robinson.paperchains;

import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v4.app.NotificationCompat;

import com.soundcloud.api.ApiWrapper;
import com.soundcloud.api.Endpoints;
import com.soundcloud.api.Params;
import com.soundcloud.api.Request;
import com.soundcloud.api.Token;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

class SoundCloudUploadTask extends AsyncTask<String, Long, JSONObject> {

    // how long to wait before removing the notification (after completion or failure)
    private static final int NOTIFICATION_REMOVAL_DELAY = 3500;

    private final WeakReference<PaperChainsActivity> mContext;

    private final NotificationManager mNotifyManager;
    private final NotificationCompat.Builder mBuilder;
    private final int notificationId = 1;

    private final ApiWrapper mApiWrapper;
    private final Token mAccessToken;
    private final String mClientId;
    private final String mUploadFileTitle;
    private final String mUploadFileDescription;
    private final String mPageId;
    private final Rect mAudioRect;

    public SoundCloudUploadTask(PaperChainsActivity context, ApiWrapper wrapper, Token accessToken, String pageId,
            Rect audioRect) {
        mContext = new WeakReference<>(context);

        // set up upload parameters
        mApiWrapper = wrapper;
        mAccessToken = accessToken;
        mClientId = context.getString(R.string.soundcloud_client_id);

        mUploadFileTitle = context.getString(R.string.audio_upload_file_title);
        mUploadFileDescription = context.getString(R.string.audio_upload_file_description);
        mPageId = pageId;
        mAudioRect = audioRect;

        // set up notifications
        mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(context);
        mBuilder.setContentTitle(context.getString(R.string.audio_upload_title))
                .setContentText(context.getString(R.string.audio_upload_progress))
                .setSmallIcon(R.drawable.ic_notification).setColor(context.getResources().getColor(R.color.primary))
                .setAutoCancel(true);
    }

    @Override
    protected JSONObject doInBackground(String... uploadFiles) {
        if (uploadFiles.length < 1) {
            return null;
        }
        final File file = new File(uploadFiles[0]);
        try {
            // @formatter:off
            Request request = Request.to(Endpoints.TRACKS).withFile(Params.Track.ASSET_DATA, file)
                    .add(Params.Track.TITLE, mUploadFileTitle).add(Params.Track.DESCRIPTION, mUploadFileDescription)
                    .add(Params.Track.TYPE, "spoken").add(Params.Track.GENRE, "storytelling")
                    .add(Params.Track.TAG_LIST,
                            "PaperChains " + "soundcloud:created-with-client-id=" + mClientId + " "
                                    + "paperchains:page-key=" + mPageId)
                    .add(Params.Track.SHARING, Params.Track.PUBLIC).add(Params.Track.STREAMABLE, true)
                    .add(Params.Track.DOWNLOADABLE, true).add(Params.Track.LICENSE, "cc-by-sa");
            // @formatter:on

            // add our app icon if possible
            final File artwork = getAppIconCacheFile(mContext.get());
            final long length;
            if (artwork != null) {
                request.withFile(Params.Track.ARTWORK_DATA, artwork);
                length = file.length() + artwork.length();
            } else {
                length = file.length();
            }

            // notify progress
            request.setProgressListener(new Request.TransferProgressListener() {
                @Override
                public void transferred(long l) throws IOException {
                    if (isCancelled()) {
                        throw new IOException("Upload cancelled");
                    }
                    publishProgress(l, length);
                }
            });

            // upload, then get the JSON response
            HttpResponse response = mApiWrapper.post(request.usingToken(mAccessToken));
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED) {
                return new JSONObject(EntityUtils.toString(response.getEntity()));
            }
            return null;

        } catch (IOException e) {
            return null;
        } catch (JSONException e) {
            return null;
        }
    }

    @Override
    protected void onProgressUpdate(Long... values) {
        // update the progress bar in the notification
        mBuilder.setProgress(values[1].intValue(), values[0].intValue(), false);
        mNotifyManager.notify(notificationId, mBuilder.build());
    }

    @Override
    protected void onPostExecute(JSONObject response) {
        // check whether we succeeded
        boolean success = false;
        long trackId = -1;
        if (response != null) {
            try {
                trackId = response.getLong("id");
                success = true;
            } catch (JSONException ignored) {
            }
        }

        // notify the activity
        PaperChainsActivity activity = mContext.get();
        if (activity != null) {
            if (success) {
                mBuilder.setContentText(activity.getString(R.string.audio_upload_completed));
                activity.audioSaveCompleted(mAudioRect, trackId);
            } else {
                mBuilder.setContentText(activity.getString(R.string.audio_upload_failed));
                activity.audioSaveFailed(R.string.hint_audio_save_failed);
            }
        }

        // finish the notification and queue its removal
        mBuilder.setProgress(0, 0, false);
        mNotifyManager.notify(notificationId, mBuilder.build());
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mNotifyManager.cancel(notificationId);
            }
        }, NOTIFICATION_REMOVAL_DELAY);
    }

    private File getAppIconCacheFile(Context context) {
        if (context == null) {
            return null;
        }

        // if we've already created the file, just return it
        File cacheFile = new File(context.getCacheDir(), "paperchains.png");
        if (cacheFile.exists()) {
            return cacheFile;
        }

        // otherwise, load from assets
        try {
            InputStream inputStream = context.getAssets().open("paperchains.png");
            // suppressed as it requires API level 19
            //noinspection TryFinallyCanBeTryWithResources
            try {
                FileOutputStream outputStream = new FileOutputStream(cacheFile);
                //noinspection TryFinallyCanBeTryWithResources
                try {
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buf)) > 0) {
                        outputStream.write(buf, 0, len);
                    }
                } finally {
                    outputStream.close();
                }
            } finally {
                inputStream.close();
            }
        } catch (IOException e) {
            return null;
        }
        return cacheFile;
    }
}