web-dev-qa-db-fra.com

Android JobScheduling - Je dois passer un objet à mon travail mais comment?

Je voudrais utiliser le nouveau JobScheduler d'Androïdes dans mon application, mais je ne sais pas comment transmettre mon objet contenant les données (tableau byte) qui devraient être envoyées via un réseau par un travail. J'ai cherché une réponse mais jusqu'à présent, je n'en ai trouvé aucune, j'ai bien peur.

J'ai un JobService:

public class MyJob extends JobService {

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        new JobTask(this).execute(jobParameters);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }

    private static class JobTask extends AsyncTask<JobParameters, Void,       JobParameters> {
        private final JobService jobService;

        public JobTask(JobService jobService) {
            this.jobService = jobService;
        }

        @Override
        protected JobParameters doInBackground(JobParameters... params) {
            AnotherClass.post(myObject); // where does myObject come from?
            return params[0];
        }

        @Override
        protected void onPostExecute(JobParameters jobParameters) {
            jobService.jobFinished(jobParameters, false);
        }
    }
}

... Je construis un travail comme celui-ci:

PersistableBundle bundle = new PersistableBundle();
JobInfo job = new JobInfo.Builder(jobID, new ComponentName(context, AshServiceJob.class))
              .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
              .setPersisted(true)
              .setExtras(bundle)  // could bundle somehow contain myObject?
              .build();

OtherClass.addJobInBackground (travail);

... et suis en train de planifier le travail:

public void addJobInBackground(final JobInfo job) {
        JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        jobScheduler.schedule(job);
    }

Sooo ... Je ne peux appeler aucune méthode directement dans MyJob, non? J'ai alors pensé que je pouvais utiliser .setExtras(bundle) pour transmettre mon objet au travail, mais comme j'ai découvert que vous ne pouvez utiliser qu'une PersistableBundle qui ne prendrait pas d'objet sérialisé comme Bundle. La définition de clés et de valeurs ne fonctionne pas, car vous ne pouvez mettre que booleans, ints, strings, etc., mais pas byte[], ce dont j'ai besoin.

Quelqu'un a une idée? Je suis assez coincé.

Merci d'avance, a-m

PS: Désolé, si je n'ai probablement pas utilisé les bons codes-tags.

12
a-m

Ok - je vais me répondre.

Il semble que transmettre des objets plus complexes que String, ints, etc. à un JobService n’est pas possible pour des raisons de persistance (le code aurait pu être modifié et les classes ne pourraient pas fonctionner avec des données anciennes). Bien sûr, cela a du sens, mais je pense qu'avec cette restriction, il est très difficile d'utiliser JobScheduling.

Ma "solution" enregistre maintenant mon objet dans un fichier et passe le nom de fichier via 

PersistableBundle bundle = new PersistableBundle();
bundle.putString("filename", object.getFilename());

Dans mon JobService, je lis ce fichier et j'envoie ses données via le réseau. Peut-être que ce n'est pas vraiment élégant, mais je ne peux pas penser à un autre moyen (meilleur). Peut-être que cela aide quelqu'un.

5
a-m

Je sais que c'est une vieille question, mais je laisserai ma solution à quiconque le jugera utile.

Je transforme d'abord mon objet en json à l'aide de Google Gson bibliothèque

MyCustomObject myObj = new MyCustomObject("data1", 123);
Gson g = new Gson();
String json = g.toJson(myObj);

PersistableBundle bundle = new PersistableBundle();
bundle.putString("MyObject", json);

Ensuite, vous récupérez la chaîne du paquet et désérialisez

String json = params.getExtras().getString("MyObject");
Gson g = new Gson();
MyCustomObject myObj = g.fromJson(json, MyCustomObject.class);
14
Tulio F.

J'ai essayé cela mais avec le FirebaseJobDispatcher:

  1. J'ai fait mon CustomObject implémente Parcelable
  2. J'ai converti mon CustomObject en chaîne 
  3. Je le mets comme un extra dans un paquet

Pour convertir CustomObject qui étend Parcelable à String: 

    private String encodeToString(CustomObject customObject) {
        Parcel parcel = Parcel.obtain();
        List< CustomObject > temp = new ArrayList<>();
        temp.add(customObject);
        parcel.writeList(temp);
        byte[] byt = parcel.marshall();
        String data = Base64.encodeToString(byt, 0, byt.length, 0);
        parcel.recycle();

        return data;
    }

Pour récupérer CustomObject qui étend Parcelable à partir de String:

       private CustomObject decodeFromString (String data) {
            byte[] byt = Base64.decode(data, 0);

            Parcel parcel = Parcel.obtain();
            parcel.unmarshall(byt, 0, byt.length);
            parcel.setDataPosition(0);

            List<CustomObject> temp = new ArrayList<>();
            parcel.readList(temp, getClass().getClassLoader());
            parcel.recycle();

            if (temp.size()>0) {
                return temp.get(0);
            } else {
                return null;
            }
        }
0
Bassem Waheed