org.catnut.service.ComposeTweetService.java Source code

Java tutorial

Introduction

Here is the source code for org.catnut.service.ComposeTweetService.java

Source

/*
 * The MIT License (MIT)
 * Copyright (c) 2014 longkai
 * The software shall be used for good, not evil.
 */
package org.catnut.service;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.provider.BaseColumns;
import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import org.catnut.R;
import org.catnut.api.TweetAPI;
import org.catnut.core.CatnutAPI;
import org.catnut.core.CatnutApp;
import org.catnut.core.CatnutProcessor;
import org.catnut.core.CatnutProvider;
import org.catnut.core.CatnutRequest;
import org.catnut.metadata.Draft;
import org.catnut.metadata.Status;
import org.catnut.metadata.User;
import org.catnut.metadata.WeiboAPIError;
import org.catnut.support.HttpClient;
import org.catnut.ui.SingleFragmentActivity;
import org.catnut.ui.TweetActivity;
import org.catnut.util.CatnutUtils;
import org.catnut.util.Constants;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * &?
 *
 * @author longkai
 */
public class ComposeTweetService extends IntentService {

    public static final String UPLOAD = CatnutAPI.API_DOMAIN + "/2/statuses/upload.json";

    public static final String TAG = "ComposeTweetService";

    private CatnutApp mApp;
    private NotificationManager mNotifyManager;
    private Notification.Builder mBuilder;

    private SendWeiboProcessor mSendWeiboProcessor;

    private final int ID = (int) (System.currentTimeMillis() / 10000);

    public ComposeTweetService() {
        super(TAG);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mApp = CatnutApp.getTingtingApp();
        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new Notification.Builder(this).setContentTitle(getString(R.string.notify_send_tweet))
                .setContentText(getString(R.string.notify_send_tweet_text)).setSmallIcon(R.drawable.ic_launcher);
    }

    // ??
    private void update(final Draft draft) {
        mApp.getRequestQueue()
                .add(new CatnutRequest(this, TweetAPI.update(draft.status, draft.visible, draft.list_id, draft.lat,
                        draft._long, null, draft.rip), mSendWeiboProcessor, null, new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                WeiboAPIError weiboAPIError = WeiboAPIError.fromVolleyError(error);
                                fallback(draft, weiboAPIError.error);
                            }
                        }))
                .setTag(TAG);
    }

    // ??&
    private void upload(Draft draft) {
        HttpClient client = new HttpClient(UPLOAD);
        InputStream inputStream = null;
        try {
            client.connectForMultipart(mApp.getAuthHeaders());
            client.addFormPart(Draft.STATUS, draft.status);
            client.addFormPart(Draft.LAT, String.valueOf(CatnutUtils.scaleNumber(draft.lat, 1)));
            client.addFormPart(Draft._LONG, String.valueOf(CatnutUtils.scaleNumber(draft._long, 1)));
            // todo: ???
            inputStream = getContentResolver().openInputStream(draft.pic);

            // ???
            int total = inputStream.available();
            int current = 0;

            ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
            int bufferSize = 2048; // 2k
            byte[] buffer = new byte[bufferSize];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                byteBuffer.write(buffer, 0, len);
                current += len;
                float progress = (current * 1.f / total) * 100;
                mBuilder.setProgress(100, (int) progress, false);
                mNotifyManager.notify(ID, mBuilder.build());
            }
            client.addFilePart(Draft.PIC, draft.pic.getLastPathSegment(), byteBuffer.toByteArray());
            client.finishMultipart();

            mBuilder.setContentText(getString(R.string.notify_waiting_result));
            mNotifyManager.notify(ID, mBuilder.build());

            // ?
            HttpClient.UploadResponse response = client.getResponse();
            Log.d(TAG, response.statusCode + " " + response.response);
            // ?
            parseNetworkResponse(response, draft);
        } catch (Exception e) {
            Log.e(TAG, "upload error!", e);
            fallback(draft, e.getLocalizedMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "i/o error!", e);
                }
            }
        }
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Draft weibo = intent.getExtras().getParcelable(Draft.DRAFT);
        mSendWeiboProcessor = new SendWeiboProcessor(weibo);
        if (weibo.pic == null) {
            update(weibo);
        } else {
            upload(weibo);
        }
    }

    /**
     * ?
     *
     * @param response
     * @throws JSONException
     */
    private void parseNetworkResponse(HttpClient.UploadResponse response, Draft draft) throws Exception {
        if (response.statusCode == 200) {
            // ?
            JSONObject json = new JSONObject(response.response);
            mSendWeiboProcessor.asyncProcess(this, json);
        } else {
            JSONObject error = new JSONObject(response.response);
            fallback(draft, error.optString(WeiboAPIError.ERROR));
        }
    }

    // ??
    private void fallback(Draft draft, String error) {
        draft.createAt = System.currentTimeMillis();
        getContentResolver().insert(CatnutProvider.parse(Draft.MULTIPLE), Draft.METADATA.convert(draft));
        mBuilder.setContentTitle(getString(R.string.post_fail)).setContentText(error)
                .setTicker(getText(R.string.post_fail)).setProgress(0, 0, false);

        // fallback
        Intent resultIntent = SingleFragmentActivity.getIntent(this, SingleFragmentActivity.DRAFT);

        TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(this);
        taskStackBuilder.addParentStack(SingleFragmentActivity.class);
        taskStackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent = taskStackBuilder.getPendingIntent(ID,
                PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(resultPendingIntent).setAutoCancel(true);
        mNotifyManager.notify(ID, mBuilder.build());
    }

    // ???
    private class SendWeiboProcessor implements CatnutProcessor<JSONObject> {

        private Draft draft;

        private SendWeiboProcessor(Draft draft) {
            this.draft = draft;
        }

        @Override
        public void asyncProcess(Context context, JSONObject json) throws Exception {
            // ?
            ContentValues tweet = Status.METADATA.convert(json);
            tweet.put(Status.TYPE, Status.HOME); // 
            getContentResolver().insert(CatnutProvider.parse(Status.MULTIPLE), tweet);
            String update = CatnutUtils.increment(true, User.TABLE, User.statuses_count, mApp.getAccessToken().uid);
            getContentResolver().update(CatnutProvider.parse(User.MULTIPLE), null, update, null);
            // status bar
            mBuilder.setContentText(getText(R.string.post_success)).setTicker(getText(R.string.post_success))
                    .setProgress(0, 0, false);

            // ?
            Intent resultIntent = new Intent(ComposeTweetService.this, TweetActivity.class);
            resultIntent.putExtra(Constants.ID, json.optLong(Constants.ID));

            TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(ComposeTweetService.this);
            taskStackBuilder.addParentStack(TweetActivity.class);
            taskStackBuilder.addNextIntent(resultIntent);
            PendingIntent resultPendingIntent = taskStackBuilder.getPendingIntent(ID,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            // ????
            if (draft.id != Integer.MIN_VALUE) {
                getContentResolver().delete(CatnutProvider.parse(Draft.MULTIPLE), BaseColumns._ID + "=" + draft.id,
                        null);
            }
            mBuilder.setContentIntent(resultPendingIntent);
            mBuilder.setAutoCancel(true);
            mNotifyManager.notify(ID, mBuilder.build());
        }
    };
}