/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple 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. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple 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 CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ /** * */ package com.csipsimple.backup; import android.annotation.TargetApi; import android.app.backup.BackupDataInputStream; import android.app.backup.BackupDataOutput; import android.app.backup.BackupHelper; import android.content.Context; import android.os.ParcelFileDescriptor; import com.csipsimple.api.SipManager; import com.csipsimple.utils.Log; import org.json.JSONArray; import org.json.JSONException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @TargetApi(8) public class SipProfilesHelper implements BackupHelper { private static final String THIS_FILE = "SipProfileHelper"; private static final String ACCOUNTS_BACKUP_KEY = "accounts"; private final Context mContext; private File databaseFile; SipProfilesHelper(Context ctxt) { mContext = ctxt; databaseFile = ctxt.getDatabasePath(SipManager.AUTHORITY); } /* * (non-Javadoc) * @see * android.app.backup.BackupHelper#performBackup(android.os.ParcelFileDescriptor * , android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) */ @Override public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) { boolean forceBackup = (oldState == null); long fileModified = databaseFile.lastModified(); try { if (!forceBackup) { FileInputStream instream = new FileInputStream(oldState.getFileDescriptor()); DataInputStream in = new DataInputStream(instream); long lastModified = in.readLong(); in.close(); if (lastModified < fileModified) { forceBackup = true; } } } catch (IOException e) { Log.e(THIS_FILE, "Cannot manage previous local backup state", e); forceBackup = true; } Log.d(THIS_FILE, "Will backup profiles ? " + forceBackup); if (forceBackup) { JSONArray accountsSaved = SipProfileJson.serializeSipProfiles(mContext); try { writeData(data, accountsSaved.toString()); } catch (IOException e) { Log.e(THIS_FILE, "Cannot manage remote backup", e); } } try { FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); DataOutputStream out = new DataOutputStream(outstream); out.writeLong(fileModified); out.close(); } catch (IOException e) { Log.e(THIS_FILE, "Cannot manage final local backup state", e); } } /* * (non-Javadoc) * @see android.app.backup.BackupHelper#restoreEntity(android.app.backup. * BackupDataInputStream) */ @Override public void restoreEntity(BackupDataInputStream data) { if (ACCOUNTS_BACKUP_KEY.equalsIgnoreCase(data.getKey())) { try { String profilesStr = readData(data); JSONArray accounts = new JSONArray(profilesStr); if (accounts != null && accounts.length() > 0) { SipProfileJson.restoreSipAccounts(mContext, accounts); } } catch (IOException e) { Log.e(THIS_FILE, "Cannot restore backup entry", e); } catch (JSONException e) { Log.e(THIS_FILE, "Cannot parse backup entry", e); } } } /* * (non-Javadoc) * @see android.app.backup.BackupHelper#writeNewStateDescription(android.os. * ParcelFileDescriptor) */ @Override public void writeNewStateDescription(ParcelFileDescriptor newState) { long fileModified = databaseFile.lastModified(); try { FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); DataOutputStream out = new DataOutputStream(outstream); out.writeLong(fileModified); out.close(); } catch (IOException e) { Log.e(THIS_FILE, "Cannot manage final local backup state", e); } } private void writeData(BackupDataOutput data, String value) throws IOException { // Create buffer stream and data output stream for our data ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); DataOutputStream outWriter = new DataOutputStream(bufStream); // Write structured data outWriter.writeUTF(value); // Send the data to the Backup Manager via the BackupDataOutput byte[] buffer = bufStream.toByteArray(); int len = buffer.length; data.writeEntityHeader(ACCOUNTS_BACKUP_KEY, len); data.writeEntityData(buffer, len); } /** * Read data from the input stream * * @param data the input stream * @return the data * @throws IOException I/O error */ private String readData(BackupDataInputStream data) throws IOException { String dataS; byte[] buf = new byte[data.size()]; data.read(buf, 0, buf.length); ByteArrayInputStream bais = new ByteArrayInputStream(buf); DataInputStream dis = new DataInputStream(bais); dataS = dis.readUTF(); dis.close(); bais.close(); return dataS; } }