/* * Copyright 2014 Gleb Godonoga. * * 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 com.andrada.sitracker.util; import android.app.backup.BackupAgent; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.os.ParcelFileDescriptor; import com.andrada.sitracker.db.beans.Author; import com.andrada.sitracker.db.beans.Publication; import com.andrada.sitracker.db.dao.AuthorDao; import com.andrada.sitracker.db.dao.PublicationDao; import com.andrada.sitracker.db.manager.SiDBHelper; import com.andrada.sitracker.events.BackUpRestoredEvent; import com.j256.ormlite.android.apptools.OpenHelperManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import de.greenrobot.event.EventBus; import static com.andrada.sitracker.util.LogUtils.LOGD; import static com.andrada.sitracker.util.LogUtils.makeLogTag; public class SiBackupAgent extends BackupAgent { private static final String TAG = makeLogTag(SiBackupAgent.class); private final static String AUTHORS_BACKUP_KEY = "authorsbackupKey"; @Override public void onBackup(ParcelFileDescriptor oldState, @NotNull BackupDataOutput data, @NotNull ParcelFileDescriptor newState) throws IOException { // Create buffer stream and data output stream for our data ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); ObjectOutputStream outWriter = new ObjectOutputStream(bufStream); try { SiDBHelper helper = new SiDBHelper(this.getApplicationContext()); PublicationDao pubDao = helper.getPublicationDao(); List<Publication> publications = pubDao.queryForAll(); LOGD(TAG, "Backing up publications. Count: " + publications.size()); // Write structured data outWriter.writeObject(publications); // Send the data to the Backup Manager via the BackupDataOutput byte[] buffer = bufStream.toByteArray(); int len = buffer.length; data.writeEntityHeader(AUTHORS_BACKUP_KEY, len); data.writeEntityData(buffer, len); FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); ObjectOutputStream out = new ObjectOutputStream(outstream); out.writeObject(publications); } catch (SQLException e) { e.printStackTrace(); } } @Override public void onRestore(@NotNull BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { while (data.readNextHeader()) { String key = data.getKey(); int dataSize = data.getDataSize(); // If the key is ours (for saving top score). Note this key was used when // we wrote the backup entity header if (AUTHORS_BACKUP_KEY.equals(key)) { // Create an input stream for the BackupDataInput byte[] dataBuf = new byte[dataSize]; data.readEntityData(dataBuf, 0, dataSize); ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf); ObjectInputStream in = null; try { LOGD(TAG, "Starting reading backup data"); in = new ObjectInputStream(baStream); Object possiblePubs = in.readObject(); if (possiblePubs instanceof List) { final List<Publication> publications = (List<Publication>) possiblePubs; SiDBHelper helper = OpenHelperManager.getHelper(this.getApplicationContext(), SiDBHelper.class); final Map<String, Author> authorsMap = new HashMap<String, Author>(); for (Publication pub : publications) { if (authorsMap.containsKey(pub.getAuthor().getUrlId())) { //Make sure the pub has the author we added first pub.setAuthor(authorsMap.get(pub.getAuthor().getUrlId())); } else { authorsMap.put(pub.getAuthor().getUrlId(), pub.getAuthor()); } } LOGD(TAG, "Backup data parsed"); final AuthorDao authorDao = helper.getAuthorDao(); final PublicationDao pubDao = helper.getPublicationDao(); assert authorDao != null; assert pubDao != null; LOGD(TAG, "Authors restored: " + authorsMap.size()); LOGD(TAG, "Total pubs restored: " + publications.size()); //Write all authors and publications in a transaction authorDao.callBatchTasks(new Callable<Object>() { @Nullable @Override public Object call() throws Exception { //Write all the authors to db. for (Author auth : authorsMap.values()) { authorDao.createOrUpdate(auth); } for (Publication pub : publications) { pubDao.createOrUpdate(pub); } return null; } }); LOGD(TAG, "Backup data persisted"); EventBus.getDefault().post(new BackUpRestoredEvent()); OpenHelperManager.releaseHelper(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (in != null) { in.close(); } } } else { // We don't know this entity key. Skip it. (Shouldn't happen.) data.skipEntityData(); } } } }