org.c99.wear_imessage.RemoteInputService.java Source code

Java tutorial

Introduction

Here is the source code for org.c99.wear_imessage.RemoteInputService.java

Source

/*
 * Copyright (c) 2015 Sam Steele
 *
 * 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 org.c99.wear_imessage;

import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Scanner;
import java.util.UUID;

public class RemoteInputService extends IntentService {
    public static final String ACTION_REPLY = "org.c99.wear_imessage.ACTION_REPLY";

    public RemoteInputService() {
        super("RemoteInputService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_REPLY.equals(action)) {
                JSONObject conversations = null, conversation = null;
                try {
                    conversations = new JSONObject(
                            getSharedPreferences("data", 0).getString("conversations", "{}"));
                } catch (JSONException e) {
                    conversations = new JSONObject();
                }

                try {
                    String key = intent.getStringExtra("service") + ":" + intent.getStringExtra("handle");
                    if (conversations.has(key)) {
                        conversation = conversations.getJSONObject(key);
                    } else {
                        conversation = new JSONObject();
                        conversations.put(key, conversation);

                        long time = new Date().getTime();
                        String tmpStr = String.valueOf(time);
                        String last4Str = tmpStr.substring(tmpStr.length() - 5);
                        conversation.put("notification_id", Integer.valueOf(last4Str));
                        conversation.put("msgs", new JSONArray());
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
                if (remoteInput != null || intent.hasExtra("reply")) {
                    String reply = remoteInput != null ? remoteInput.getCharSequence("extra_reply").toString()
                            : intent.getStringExtra("reply");

                    if (intent.hasExtra(Intent.EXTRA_STREAM)) {
                        NotificationCompat.Builder notification = new NotificationCompat.Builder(this)
                                .setContentTitle("Uploading File").setProgress(0, 0, true).setLocalOnly(true)
                                .setOngoing(true).setSmallIcon(android.R.drawable.stat_sys_upload);
                        NotificationManagerCompat.from(this).notify(1337, notification.build());

                        InputStream fileIn = null;
                        InputStream responseIn = null;
                        HttpURLConnection http = null;
                        try {
                            String filename = "";
                            int total = 0;
                            String type = getContentResolver()
                                    .getType((Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM));
                            if (type == null || type.length() == 0)
                                type = "application/octet-stream";
                            fileIn = getContentResolver()
                                    .openInputStream((Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM));

                            Cursor c = getContentResolver().query(
                                    (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM),
                                    new String[] { OpenableColumns.SIZE, OpenableColumns.DISPLAY_NAME }, null, null,
                                    null);
                            if (c != null && c.moveToFirst()) {
                                total = c.getInt(0);
                                filename = c.getString(1);
                                c.close();
                            } else {
                                total = fileIn.available();
                            }

                            String boundary = UUID.randomUUID().toString();
                            http = (HttpURLConnection) new URL(
                                    "http://" + getSharedPreferences("prefs", 0).getString("host", "") + "/upload")
                                            .openConnection();
                            http.setReadTimeout(60000);
                            http.setConnectTimeout(60000);
                            http.setDoOutput(true);
                            http.setFixedLengthStreamingMode(total + (boundary.length() * 5) + filename.length()
                                    + type.length() + intent.getStringExtra("handle").length()
                                    + intent.getStringExtra("service").length() + reply.length() + 251);
                            http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

                            OutputStream out = http.getOutputStream();
                            out.write(("--" + boundary + "\r\n").getBytes());
                            out.write(("Content-Disposition: form-data; name=\"handle\"\r\n\r\n").getBytes());
                            out.write((intent.getStringExtra("handle") + "\r\n").getBytes());
                            out.write(("--" + boundary + "\r\n").getBytes());
                            out.write(("Content-Disposition: form-data; name=\"service\"\r\n\r\n").getBytes());
                            out.write((intent.getStringExtra("service") + "\r\n").getBytes());
                            out.write(("--" + boundary + "\r\n").getBytes());
                            out.write(("Content-Disposition: form-data; name=\"msg\"\r\n\r\n").getBytes());
                            out.write((reply + "\r\n").getBytes());
                            out.write(("--" + boundary + "\r\n").getBytes());
                            out.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + filename
                                    + "\"\r\n").getBytes());
                            out.write(("Content-Type: " + type + "\r\n\r\n").getBytes());

                            byte[] buffer = new byte[8192];
                            int count = 0;
                            int n = 0;
                            while (-1 != (n = fileIn.read(buffer))) {
                                out.write(buffer, 0, n);
                                count += n;

                                float progress = (float) count / (float) total;
                                if (progress < 1.0f)
                                    notification.setProgress(1000, (int) (progress * 1000), false);
                                else
                                    notification.setProgress(0, 0, true);
                                NotificationManagerCompat.from(this).notify(1337, notification.build());
                            }

                            out.write(("\r\n--" + boundary + "--\r\n").getBytes());
                            out.flush();
                            out.close();
                            if (http.getResponseCode() == HttpURLConnection.HTTP_OK) {
                                responseIn = http.getInputStream();
                                StringBuilder sb = new StringBuilder();
                                Scanner scanner = new Scanner(responseIn).useDelimiter("\\A");
                                while (scanner.hasNext()) {
                                    sb.append(scanner.next());
                                }
                                android.util.Log.i("iMessage", "Upload result: " + sb.toString());
                                try {
                                    if (conversation != null) {
                                        JSONArray msgs = conversation.getJSONArray("msgs");
                                        JSONObject m = new JSONObject();
                                        m.put("msg", filename);
                                        m.put("service", intent.getStringExtra("service"));
                                        m.put("handle", intent.getStringExtra("handle"));
                                        m.put("type", "sent_file");
                                        msgs.put(m);

                                        while (msgs.length() > 10) {
                                            msgs.remove(0);
                                        }

                                        GCMIntentService.notify(getApplicationContext(),
                                                intent.getIntExtra("notification_id", 0), msgs, intent, true);
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            } else {
                                responseIn = http.getErrorStream();
                                StringBuilder sb = new StringBuilder();
                                Scanner scanner = new Scanner(responseIn).useDelimiter("\\A");
                                while (scanner.hasNext()) {
                                    sb.append(scanner.next());
                                }
                                android.util.Log.e("iMessage", "Upload failed: " + sb.toString());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (responseIn != null)
                                    responseIn.close();
                            } catch (Exception ignore) {
                            }
                            try {
                                if (http != null)
                                    http.disconnect();
                            } catch (Exception ignore) {
                            }
                            try {
                                fileIn.close();
                            } catch (Exception ignore) {
                            }
                        }
                        NotificationManagerCompat.from(this).cancel(1337);
                    } else if (reply.length() > 0) {
                        URL url = null;
                        try {
                            url = new URL("http://" + getSharedPreferences("prefs", 0).getString("host", "")
                                    + "/send?service=" + intent.getStringExtra("service") + "&handle="
                                    + intent.getStringExtra("handle") + "&msg="
                                    + URLEncoder.encode(reply, "UTF-8"));
                        } catch (Exception e) {
                            e.printStackTrace();
                            return;
                        }
                        HttpURLConnection conn;

                        try {
                            conn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
                        } catch (IOException e) {
                            e.printStackTrace();
                            return;
                        }
                        conn.setConnectTimeout(5000);
                        conn.setReadTimeout(5000);
                        conn.setUseCaches(false);

                        BufferedReader reader = null;

                        try {
                            if (conn.getInputStream() != null) {
                                reader = new BufferedReader(new InputStreamReader(conn.getInputStream()), 512);
                            }
                        } catch (IOException e) {
                            if (conn.getErrorStream() != null) {
                                reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()), 512);
                            }
                        }

                        if (reader != null) {
                            try {
                                reader.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        conn.disconnect();
                        try {
                            if (conversation != null) {
                                JSONArray msgs = conversation.getJSONArray("msgs");
                                JSONObject m = new JSONObject();
                                m.put("msg", reply);
                                m.put("service", intent.getStringExtra("service"));
                                m.put("handle", intent.getStringExtra("handle"));
                                m.put("type", "sent");
                                msgs.put(m);

                                while (msgs.length() > 10) {
                                    msgs.remove(0);
                                }

                                GCMIntentService.notify(getApplicationContext(),
                                        intent.getIntExtra("notification_id", 0), msgs, intent, true);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    SharedPreferences.Editor e = getSharedPreferences("data", 0).edit();
                    e.putString("conversations", conversations.toString());
                    e.apply();
                }
            }
        }
    }
}