Android - запуск службы при загрузке без активности - PullRequest
0 голосов
/ 22 ноября 2018

Проблема:

В Android нет способа указать отдельные папки в папке DCIM, которые вы хотите синхронизировать с облаком.Приложение Facebook сохраняет изображения в DCIM / Facebook, поэтому любое сохраненное изображение автоматически синхронизируется с облаком.Я могу решить эту проблему, поместив файл .NOMEDIA в папку, но теперь это означает, что я не могу просматривать файлы, не заходя в проводник, поэтому я теряю легкий доступ, например, для отправки этих изображений в сообщениях.

В настоящее время я работаю над приложением Android для автоматического перемещения файлов, кроме файла .NOMDEIA, из DCIM / Facebook в Pictures / Facebook.В настоящее время у меня есть код, который будет делать это в классе MainActivity, и я хочу преобразовать его в службу, которая будет запускаться автоматически.

Короче говоря, я хочу, чтобы эта служба запускалась при загрузке и всегда работала без отображенияактивность, так что отнимает все ручные усилия с моей стороны.Опять же, я не хочу запускать что-либо вручную и не вижу необходимости в действиях, поскольку не хочу никакого взаимодействия с пользователем.Я прочитал много страниц, заблудился в документации и, по-видимому, был на бесчисленных постах, касающихся Service, IntentService, JobScheduler и т. Д., И в настоящее время я крутлю свои колеса как на реализацию, так и на правильный подход.

Является ли этохороший случай для JobSchedule, который запускается каждые несколько секунд?Должна ли это быть служба, которая запускает код снова и снова в цикле, который ждет несколько секунд в каждой итерации?Можно ли вызвать службу при добавлении чего-либо в папку?

Как уже упоминалось выше, я боролся с реализацией.На данный момент единственное, что мне удалось сделать, - это вызвать службу из MainActivity, но это происходит, когда действие кратковременно открывается и закрывается.Это нежелательное поведение.Ситуация становится немного запутанной, поэтому я решил не включать какой-либо код в надежде, что кто-то может либо указать мне на правильную документацию / учебное пособие, либо предоставить надлежащий скелет, с которым я могу работать.Я бы предпочел не мутить воду с самого начала.

Важное примечание: у меня есть реализация с запросом активности для READ_EXTERNAL_STORAGE (насколько я понимаю, вам не нужно запрашивать разрешение для WRITE_EXTERNAL_STORAGE; мой кодработает без запроса такого разрешения), но я также не уверен, как это сделать для службы, поскольку метод запроса разрешений, по-видимому, требует активности в качестве одного из параметров.

Редактировать: Добавление манифеста и кода дляполучатель и сервис

FacebookImageListener.java

public class FacebookImageListener extends BroadcastReceiver {


    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, FacebookImageMoverService.class));
        Log.i("FacebookImageMoverService", "started");
    }
}

FacebookImageMoverService.java

public class FacebookImageMoverService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        while (true) {

            //TODO remove this
            Log.i("imagemover", "DELETE THIS");

//            String path = this.getExternalFilesDir(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/Facebook";
            String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/Facebook";
            Log.d("Files", "Path: " + path);
            File directory = new File(path);
            File[] files = directory.listFiles();

            Log.d("Files", "Size: " + files.length);
            for (int i = 0; i < files.length; i++) {
                Toast toast = Toast.makeText(this.getApplicationContext(), "FileName:" + files[i].getName(), Toast.LENGTH_LONG);
                toast.show();
                Log.d("Files", "FileName:" + files[i].getName());

                if (!files[i].getName().equals(".NOMEDIA")) {
//                    moveFile(path + "/", files[i].getName(), this.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/Facebook/");
                    moveFile(path + "/", files[i].getName(), Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/Facebook/");
                }
            }

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        //TODO check this out
//        return Service.START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        //TODO for communication return IBinder implementation
        return null;
    }

    private void moveFile(String inputPath, String inputFile, String outputPath) {

        InputStream in = null;
        OutputStream out = null;
        try {

            //create output directory if it doesn't exist
            File dir = new File(outputPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }


            in = new FileInputStream(inputPath + inputFile);
            out = new FileOutputStream(outputPath + inputFile);

            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }
            in.close();
            in = null;

            // write the output file
            out.flush();
            out.close();
            out = null;

            // delete the original file
            new File(inputPath + inputFile).delete();


        } catch (FileNotFoundException fnfe1) {
            Log.e("tag", fnfe1.getMessage());
        } catch (Exception e) {
            Log.e("tag", e.getMessage());
        }

    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="shogg.facebookimagemover"
    >

    <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
    <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />-->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


    <application android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round">

        <receiver android:name=".FacebookImageListener"
            android:icon="@mipmap/ic_launcher"
            android:exported="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>

        <service android:enabled="true" android:name=".FacebookImageMoverService" />
    </application>


</manifest>

1 Ответ

0 голосов
/ 23 ноября 2018

Зарегистрируйте BroadcastReceiver в своем AndroidManifest.xml и запросите разрешение на прослушивание загрузочных передач устройства, добавив это разрешение в манифест:

android:permission="android.permission.RECEIVE_BOOT_COMPLETED">

Затем можно запуститьваш сервис по методу onReceive() вашего BroadcastListerner без запуска основной активности вашего приложения, препятствующей пользователю каким-либо образом.

...