eu.codeplumbers.cosi.services.CosiFileService.java Source code

Java tutorial

Introduction

Here is the source code for eu.codeplumbers.cosi.services.CosiFileService.java

Source

/*
 *     Cos android client for Cozy Cloud
 *
 *     Copyright (C)  2016 Hamza Abdelkebir
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package eu.codeplumbers.cosi.services;

import android.app.IntentService;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.support.v7.app.NotificationCompat;
import android.util.Base64;
import android.util.Log;

import org.apache.commons.io.IOUtils;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import eu.codeplumbers.cosi.R;
import eu.codeplumbers.cosi.db.models.Device;
import eu.codeplumbers.cosi.db.models.File;
import eu.codeplumbers.cosi.services.events.FileSyncEvent;
import eu.codeplumbers.cosi.utils.Constants;
import eu.codeplumbers.cosi.utils.FileUtils;

import static eu.codeplumbers.cosi.utils.Constants.REFRESH;
import static eu.codeplumbers.cosi.utils.Constants.SERVICE_ERROR;
import static eu.codeplumbers.cosi.utils.Constants.SYNC_MESSAGE;

/**
 * Created by thor on 10/29/16.
 */

public class CosiFileService extends IntentService {

    private List<File> allFiles;
    private String errorMessage;
    private String authHeader;
    private String folderUrl;
    private String fileUrl;

    private int notification_id = 1340;
    private NotificationManager mNotifyManager;
    private NotificationCompat.Builder mBuilder;
    private boolean mSyncRunning;
    private boolean stopSync;

    public CosiFileService() {
        super("CosiFileService");

        stopSync = false;
        mSyncRunning = false;
    }

    public CosiFileService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Do the task here
        Log.i(CosiFileService.class.getName(), "Cosi Service running");

        // Release the wake lock provided by the WakefulBroadcastReceiver.
        WakefulBroadcastReceiver.completeWakefulIntent(intent);

        allFiles = new ArrayList<>();

        Device device = Device.registeredDevice();

        // cozy register device url
        folderUrl = device.getUrl() + "/ds-api/request/folder/cosiall/";
        fileUrl = device.getUrl() + "/ds-api/request/file/cosiall/";

        // concatenate username and password with colon for authentication
        final String credentials = device.getLogin() + ":" + device.getPassword();
        authHeader = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

        showNotification();

        if (isNetworkAvailable()) {
            try {
                // read local sms log first
                getAllRemoteFolders();
                getAllRemoteFiles();

                mBuilder.setContentText(getString(R.string.lbl_sms_sync_done));
                mBuilder.setProgress(0, 0, false);
                mNotifyManager.notify(notification_id, mBuilder.build());

                if (!allFiles.isEmpty()) {
                    mNotifyManager.cancel(notification_id);
                    EventBus.getDefault().post(new FileSyncEvent(REFRESH, "Sync OK"));
                } else {
                    EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, "Sync failed"));
                }

            } catch (Exception e) {
                e.printStackTrace();
                mSyncRunning = false;
                EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            }
        } else {
            mSyncRunning = false;
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, "No Internet connection"));
            mBuilder.setContentText("Sync failed because no Internet connection was available");
            mNotifyManager.notify(notification_id, mBuilder.build());
        }
    }

    private void getAllRemoteFiles() {
        URL urlO = null;
        try {
            urlO = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) urlO.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            conn.setRequestProperty("Authorization", authHeader);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");

            // read the response
            int status = conn.getResponseCode();
            InputStream in = null;

            if (status >= HttpURLConnection.HTTP_BAD_REQUEST) {
                in = conn.getErrorStream();
            } else {
                in = conn.getInputStream();
            }

            StringWriter writer = new StringWriter();
            IOUtils.copy(in, writer, "UTF-8");
            String result = writer.toString();

            JSONArray jsonArray = new JSONArray(result);

            if (jsonArray != null) {
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject fileJson = jsonArray.getJSONObject(i).getJSONObject("value");
                    File file = File.getByRemoteId(fileJson.get("_id").toString());

                    if (file == null) {
                        file = new File(fileJson, false);
                    } else {
                        file.setName(fileJson.getString("name"));
                        file.setPath(fileJson.getString("path"));
                        file.setCreationDate(fileJson.getString("creationDate"));
                        file.setLastModification(fileJson.getString("lastModification"));
                        file.setTags(fileJson.getString("tags"));

                        if (fileJson.has("binary")) {
                            file.setBinary(fileJson.getJSONObject("binary").toString());
                        }

                        file.setIsFile(true);
                        file.setFileClass(fileJson.getString("class"));
                        file.setMimeType(fileJson.getString("mime"));
                        file.setSize(fileJson.getLong("size"));
                    }

                    mBuilder.setProgress(jsonArray.length(), i, false);
                    mBuilder.setContentText("Indexing file : " + file.getName());
                    mNotifyManager.notify(notification_id, mBuilder.build());

                    EventBus.getDefault()
                            .post(new FileSyncEvent(SYNC_MESSAGE, "Indexing file : " + file.getName()));

                    file.setDownloaded(FileUtils.checkFileExists(Environment.getExternalStorageDirectory()
                            + java.io.File.separator + Constants.APP_DIRECTORY + java.io.File.separator + "files"
                            + file.getPath() + "/" + file.getName()));
                    file.save();

                    allFiles.add(file);
                }
            } else {
                EventBus.getDefault()
                        .post(new FileSyncEvent(SERVICE_ERROR, new JSONObject(result).getString("error")));
                mNotifyManager.notify(notification_id, mBuilder.build());
                stopSelf();
            }

            in.close();
            conn.disconnect();

        } catch (MalformedURLException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (ProtocolException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (IOException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (JSONException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        }
    }

    private void getAllRemoteFolders() {
        //File.deleteAllFolders();

        URL urlO = null;
        try {
            urlO = new URL(folderUrl);
            HttpURLConnection conn = (HttpURLConnection) urlO.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            conn.setRequestProperty("Authorization", authHeader);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");

            // read the response
            int status = conn.getResponseCode();
            InputStream in = null;

            if (status >= HttpURLConnection.HTTP_BAD_REQUEST) {
                in = conn.getErrorStream();
            } else {
                in = conn.getInputStream();
            }

            StringWriter writer = new StringWriter();
            IOUtils.copy(in, writer, "UTF-8");
            String result = writer.toString();

            JSONArray jsonArray = new JSONArray(result);

            if (jsonArray != null) {
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject folderJson = jsonArray.getJSONObject(i).getJSONObject("value");
                    File file = File.getByRemoteId(folderJson.get("_id").toString());

                    if (file == null) {
                        file = new File(folderJson, true);
                    } else {
                        file.setName(folderJson.getString("name"));
                        file.setPath(folderJson.getString("path"));
                        file.setCreationDate(folderJson.getString("creationDate"));
                        file.setLastModification(folderJson.getString("lastModification"));
                        file.setTags(folderJson.getString("tags"));
                    }

                    mBuilder.setProgress(jsonArray.length(), i, false);
                    mBuilder.setContentText("Indexing remote folder : " + file.getName());
                    mNotifyManager.notify(notification_id, mBuilder.build());

                    EventBus.getDefault()
                            .post(new FileSyncEvent(SYNC_MESSAGE, "Indexing remote folder : " + file.getName()));

                    file.save();
                    createFolder(file.getPath(), file.getName());

                    allFiles.add(file);
                }
            } else {
                EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, "Failed to parse API response"));
                stopSelf();
            }

            in.close();
            conn.disconnect();

        } catch (MalformedURLException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (ProtocolException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (IOException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        } catch (JSONException e) {
            e.printStackTrace();
            EventBus.getDefault().post(new FileSyncEvent(SERVICE_ERROR, e.getLocalizedMessage()));
            stopSelf();
        }
    }

    private void createFolder(String path, String folderName) {
        java.io.File dir = new java.io.File(
                Environment.getExternalStorageDirectory() + java.io.File.separator + Constants.APP_DIRECTORY
                        + java.io.File.separator + "files" + (path.equals("") ? "/" : path + "/") + folderName);
        if (!dir.exists()) {
            Log.d("Cosi", "Creating folder:" + dir.getAbsolutePath());
            dir.mkdirs();
        }
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
                Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }

    public void showNotification() {
        mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setContentTitle(getString(R.string.lbl_files))
                .setContentText(getString(R.string.lbl_notes_ongoing_sync))
                .setSmallIcon(R.drawable.ic_call_black_24dp).setOngoing(true);

    }
}