17

我想在我的应用程序中使用 Android 的新 JobScheduler,但现在我不知道如何传递我的对象,该对象包含byte应由作业通过网络发送的数据(数组)。我搜索了一个答案,但到目前为止我害怕没有找到答案。

我有一个 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);
        }
    }
}

...正在建立这样的工作:

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(job);

...并且正在安排工作:

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

Sooo ...我不能直接调用 MyJob 中的任何方法,对吧?然后我想我可以.setExtras(bundle)用来将我的对象传递给工作,但是我发现你只能使用一个PersistableBundle不会像 Bundle 这样的序列化对象。设置键和值是行不通的,因为你只能 putbooleans, ints, strings等,但不能byte[],这正是我所需要的。

有人知道吗?我很困惑。

提前谢谢,我

PS:对不起,如果我可能没有使用正确的代码标签。

4

4 回答 4

16

我知道这是一个老问题,但我会把我的解决方案留给那些觉得它有用的人。

首先,我使用 Google Gson库将我的对象转换为 json

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

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

然后从包中检索字符串并反序列化

String json = params.getExtras().getString("MyObject");
Gson g = new Gson();
MyCustomObject myObj = g.fromJson(json, MyCustomObject.class);
于 2016-03-22T20:03:07.757 回答
7

好的 - 我会回答自己。

由于持久性原因,似乎不可能将比字符串、整数等更复杂的对象传递给 JobService(代码可能已经更改,而不是类将无法处理旧数据)。这当然是有道理的,但我认为有这个限制很难使用 JobScheduling。

我的“解决方案”现在是将我的对象保存在文件中并通过

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

在我的 JobService 中,我正在读取该文件并通过网络发送它的数据。也许它不是很优雅,但我想不出另一种(更好的)方式。也许这对某人有帮助。

于 2015-12-03T10:04:54.877 回答
0

我试过了,但使用 FirebaseJobDispatcher:

  1. 我让我的 CustomObject 实现 Parcelable
  2. 我将我的 CustomObject 转换为字符串
  3. 我把它作为一个额外的包

要将扩展 Parcelable 的 CustomObject 转换为 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;
    }

要从 String 检索扩展 Parcelable 的 CustomObject:

       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;
            }
        }
于 2019-01-15T13:53:57.313 回答
0

如果自定义对象通过作业服务中的意图传递,类加载器信息将丢失。

可以通过设置额外的类加载器来解决。

intent.setExtrasClassLoader(<CUSTOM CLASS>.class.getClassLoader());
于 2020-11-05T03:22:59.643 回答