Skip to content

Commit dac04b4

Browse files
author
andybryant
committed
added beginnings of backup/sync code
git-svn-id: http://android-shuffle.googlecode.com/svn/trunk@68 c433d9f2-e643-0410-a449-b9b772e888ec
1 parent 8f0cd7c commit dac04b4

19 files changed

+3163
-3
lines changed

client/.classpath

+2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
<classpathentry kind="src" path="src"/>
44
<classpathentry kind="src" path="gen"/>
55
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6+
<classpathentry combineaccessrules="false" kind="src" path="/Shuffle-DTO"/>
7+
<classpathentry kind="lib" path="/Shuffle-DTO/lib/protobuf-java-2.1.0.jar"/>
68
<classpathentry kind="output" path="bin"/>
79
</classpath>

client/.project

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<projectDescription>
3-
<name>Android-Shuffle</name>
3+
<name>Shuffle-Android</name>
44
<comment></comment>
55
<projects>
66
</projects>

client/AndroidManifest.xml

+24-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
<uses-sdk android:minSdkVersion="3" />
2424

25+
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
26+
<uses-permission android:name="android.permission.WRITE_OWNER_DATA" />
2527
<uses-permission android:name="android.permission.READ_CALENDAR" />
2628
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
2729

@@ -198,7 +200,8 @@
198200
</activity>
199201

200202

201-
<activity android:name=".activity.PreferencesActivity" android:label="@string/title_preferences">
203+
<activity android:name=".activity.PreferencesActivity"
204+
android:label="@string/title_preferences">
202205
<intent-filter>
203206
<action android:name="android.intent.action.VIEW" />
204207
<action android:name="android.intent.action.EDIT" />
@@ -208,7 +211,26 @@
208211
</intent-filter>
209212
</activity>
210213

211-
<activity android:name=".activity.PreferencesAppearanceActivity" android:label="@string/title_preferences_appearance">
214+
<activity android:name=".activity.PreferencesAppearanceActivity"
215+
android:label="@string/title_preferences_appearance">
216+
</activity>
217+
218+
<activity android:name=".activity.PreferencesCreateBackupActivity"
219+
android:label="@string/title_preferences_create_backup"
220+
android:theme="@android:style/Theme.Dialog">
221+
<intent-filter>
222+
<action android:name="android.intent.action.VIEW" />
223+
<action android:name="android.intent.action.MAIN" />
224+
</intent-filter>
225+
</activity>
226+
227+
<activity android:name=".activity.PreferencesRestoreBackupActivity"
228+
android:label="@string/title_preferences_restore_backup"
229+
android:theme="@android:style/Theme.Dialog">
230+
<intent-filter>
231+
<action android:name="android.intent.action.VIEW" />
232+
<action android:name="android.intent.action.MAIN" />
233+
</intent-filter>
212234
</activity>
213235

214236
<activity android:name=".activity.PreferencesDeleteCompletedActivity"

client/res/layout/backup_create.xml

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2009 Android Shuffle Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
17+
android:padding="4dip"
18+
android:layout_width="fill_parent" android:layout_height="fill_parent"
19+
android:paddingBottom="10px" style="@style/editor">
20+
21+
<TextView android:id="@+id/filename_label"
22+
android:layout_width="fill_parent"
23+
android:layout_height="wrap_content"
24+
android:layout_alignParentLeft="true"
25+
android:layout_alignParentTop="true"
26+
android:paddingLeft="5px"
27+
android:paddingRight="5px"
28+
android:text="@string/filename_title"
29+
style="@style/label"
30+
/>
31+
32+
<EditText android:id="@+id/filename" android:layout_width="fill_parent"
33+
android:layout_height="wrap_content"
34+
android:layout_alignParentLeft="true"
35+
android:layout_below="@+id/filename_label"
36+
android:singleLine="true"
37+
android:maxLength="50"
38+
style="@style/text_editable"
39+
>
40+
<requestFocus />
41+
</EditText>
42+
43+
<View android:id="@+id/end_separator"
44+
android:layout_width="fill_parent"
45+
android:layout_height="1dip"
46+
android:layout_below="@+id/filename"
47+
android:background="@android:drawable/divider_horizontal_bright"
48+
/>
49+
50+
<include android:id="@+id/save_panel" layout="@layout/editor_save_panel"
51+
android:layout_width="fill_parent"
52+
android:layout_height="wrap_content"
53+
android:layout_alignParentLeft="true"
54+
android:layout_alignParentBottom="true"
55+
/>
56+
57+
</RelativeLayout>

client/res/layout/backup_restore.xml

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2009 Android Shuffle Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
17+
android:padding="4dip"
18+
android:layout_width="fill_parent" android:layout_height="fill_parent"
19+
android:paddingBottom="10px" style="@style/editor">
20+
21+
<TextView android:id="@+id/filename_label"
22+
android:layout_width="fill_parent"
23+
android:layout_height="wrap_content"
24+
android:layout_alignParentLeft="true"
25+
android:layout_alignParentTop="true"
26+
android:paddingLeft="5px"
27+
android:paddingRight="5px"
28+
android:text="@string/filename_title"
29+
style="@style/label"
30+
/>
31+
32+
<Spinner android:id="@+id/filename" android:layout_width="fill_parent"
33+
android:layout_height="wrap_content"
34+
android:layout_alignParentLeft="true"
35+
android:layout_below="@+id/filename_label"
36+
>
37+
</Spinner>
38+
39+
<View android:id="@+id/end_separator"
40+
android:layout_width="fill_parent"
41+
android:layout_height="1dip"
42+
android:layout_below="@+id/filename"
43+
android:background="@android:drawable/divider_horizontal_bright"
44+
/>
45+
46+
<include android:id="@+id/save_panel" layout="@layout/editor_save_panel"
47+
android:layout_width="fill_parent"
48+
android:layout_height="wrap_content"
49+
android:layout_alignParentLeft="true"
50+
android:layout_alignParentBottom="true"
51+
/>
52+
53+
</RelativeLayout>

client/res/values/strings.xml

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
<string name="title_preferences">General Settings</string>
3434
<string name="title_preferences_appearance">General Settings > Action appearance</string>
3535
<string name="title_preferences_clean">General Settings > Clean up</string>
36+
<string name="title_preferences_create_backup">General Settings > Create backup</string>
37+
<string name="title_preferences_restore_backup">General Settings > Restore from backup</string>
3638
<string name="title_help">Help</string>
3739
<string name="title_icon_picker">Choose icon</string>
3840
<string name="title_colour_picker">Choose color</string>
@@ -122,6 +124,7 @@
122124
<string name="context_name_title">Context Name</string>
123125
<string name="due_date_title">Due Date</string>
124126

127+
125128
<string name="layout_preferences">Layout</string>
126129

127130
<string name="title_project_view_preference">Project View</string>
@@ -133,6 +136,18 @@
133136
<string name="title_action_appearance_preference">Action appearance</string>
134137
<string name="summary_action_appearance_preference">Customize display of actions in lists</string>
135138

139+
140+
<string name="backup_preferences">Backup</string>
141+
142+
<string name="title_create_backup_preference">Backup to SD Card</string>
143+
<string name="summary_create_backup_preference">Save all actions, projects and contexts</string>
144+
145+
<string name="filename_title">Backup file</string>
146+
<string name="toast_backup_saved">Data successfully backed up to<xliff:g id="filename">%s</xliff:g>.</string>
147+
148+
<string name="title_restore_backup_preference">Restore from SD Card</string>
149+
<string name="summary_restore_backup_preference">Recover data from backup</string>
150+
136151
<string name="cleanup_preferences">Clean up</string>
137152

138153
<string name="dialog_title_cleanup_preference">Delete completed actions</string>

client/res/xml/preferences.xml

+23
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,29 @@
4545

4646
</PreferenceCategory>
4747

48+
<PreferenceCategory
49+
android:title="@string/backup_preferences">
50+
51+
<PreferenceScreen
52+
android:title="@string/title_create_backup_preference"
53+
android:summary="@string/summary_create_backup_preference">
54+
55+
<intent android:action="android.intent.action.MAIN"
56+
android:targetPackage="org.dodgybits.android.shuffle"
57+
android:targetClass="org.dodgybits.android.shuffle.activity.PreferencesCreateBackupActivity" />
58+
</PreferenceScreen>
59+
60+
<PreferenceScreen
61+
android:title="@string/title_restore_backup_preference"
62+
android:summary="@string/summary_restore_backup_preference">
63+
64+
<intent android:action="android.intent.action.MAIN"
65+
android:targetPackage="org.dodgybits.android.shuffle"
66+
android:targetClass="org.dodgybits.android.shuffle.activity.PreferencesRestoreBackupActivity" />
67+
</PreferenceScreen>
68+
69+
</PreferenceCategory>
70+
4871
<PreferenceCategory
4972
android:title="@string/cleanup_preferences">
5073

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package org.dodgybits.android.shuffle.activity;
2+
3+
import java.io.File;
4+
import java.io.FileOutputStream;
5+
import java.io.IOException;
6+
import java.io.OutputStream;
7+
import java.text.SimpleDateFormat;
8+
import java.util.Date;
9+
10+
import org.dodgybits.android.shuffle.R;
11+
import org.dodgybits.android.shuffle.model.Context;
12+
import org.dodgybits.android.shuffle.model.Project;
13+
import org.dodgybits.android.shuffle.model.Task;
14+
import org.dodgybits.android.shuffle.provider.Shuffle;
15+
import org.dodgybits.android.shuffle.util.BindingUtils;
16+
import org.dodgybits.shuffle.dto.ShuffleProtos.Catalogue;
17+
import org.dodgybits.shuffle.dto.ShuffleProtos.Catalogue.Builder;
18+
19+
import android.app.Activity;
20+
import android.database.Cursor;
21+
import android.os.Bundle;
22+
import android.os.Environment;
23+
import android.text.TextUtils;
24+
import android.util.Log;
25+
import android.view.View;
26+
import android.widget.EditText;
27+
import android.widget.Toast;
28+
29+
public class PreferencesCreateBackupActivity extends Activity
30+
implements View.OnClickListener {
31+
private static final String cTag = "PreferencesCreateBackupActivity";
32+
33+
private EditText mFilenameWidget;
34+
35+
@Override
36+
protected void onCreate(Bundle icicle) {
37+
Log.d(cTag, "onCreate+");
38+
super.onCreate(icicle);
39+
setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
40+
41+
setContentView(R.layout.backup_create);
42+
43+
mFilenameWidget = (EditText) findViewById(R.id.filename);
44+
Date today = new Date();
45+
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
46+
String defaultText = "shuffle-" + formatter.format(today) + ".bak";
47+
mFilenameWidget.setText(defaultText);
48+
49+
addSavePanelListeners();
50+
}
51+
52+
public void onClick(View v) {
53+
switch (v.getId()) {
54+
55+
case R.id.saveButton:
56+
createBackup();
57+
break;
58+
59+
case R.id.discardButton:
60+
finish();
61+
break;
62+
}
63+
}
64+
65+
private void addSavePanelListeners() {
66+
// Setup the bottom buttons
67+
View view = findViewById(R.id.saveButton);
68+
view.setOnClickListener(this);
69+
view = findViewById(R.id.discardButton);
70+
view.setOnClickListener(this);
71+
}
72+
73+
private void createBackup() {
74+
String filename = mFilenameWidget.getText().toString();
75+
if (TextUtils.isEmpty(filename)) {
76+
// TODO show alert
77+
Log.e(cTag, "Filename was empty");
78+
return;
79+
}
80+
81+
String storage_state = Environment.getExternalStorageState();
82+
if (! Environment.MEDIA_MOUNTED.equals(storage_state)) {
83+
// TODO show alert
84+
Log.e(cTag, "Media is not mounted: " + storage_state);
85+
return;
86+
}
87+
88+
File dir = Environment.getExternalStorageDirectory();
89+
File backupFile = new File(dir, filename);
90+
try {
91+
backupFile.createNewFile();
92+
FileOutputStream out = new FileOutputStream(backupFile);
93+
writeBackup(out);
94+
} catch (IOException ioe) {
95+
// TODO show alert
96+
Log.e(cTag, "Failed to create backup " + ioe.getMessage());
97+
return;
98+
}
99+
100+
String text = getResources().getString(R.string.toast_backup_saved, filename);
101+
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
102+
finish();
103+
}
104+
105+
private void writeBackup(OutputStream out) throws IOException {
106+
// TODO display progress
107+
Builder builder = Catalogue.newBuilder();
108+
109+
// write contexts
110+
Cursor contextCursor = getContentResolver().query(
111+
Shuffle.Contexts.CONTENT_URI, Shuffle.Contexts.cFullProjection,
112+
null, null, null);
113+
while (contextCursor.moveToNext()) {
114+
Context context = BindingUtils.readContext(contextCursor, getResources());
115+
builder.addContext(context.toDto());
116+
}
117+
contextCursor.close();
118+
119+
// write projects
120+
Cursor projectCursor = getContentResolver().query(
121+
Shuffle.Projects.CONTENT_URI, Shuffle.Projects.cFullProjection,
122+
null, null, null);
123+
while (projectCursor.moveToNext()) {
124+
Project project = BindingUtils.readProject(projectCursor);
125+
builder.addProject(project.toDto());
126+
}
127+
projectCursor.close();
128+
129+
// write tasks
130+
Cursor taskCursor = getContentResolver().query(
131+
Shuffle.Tasks.CONTENT_URI, Shuffle.Tasks.cFullProjection,
132+
null, null, null);
133+
while (taskCursor.moveToNext()) {
134+
Task task = BindingUtils.readTask(taskCursor, getResources());
135+
builder.addTask(task.toDto());
136+
}
137+
taskCursor.close();
138+
139+
builder.build().writeTo(out);
140+
out.close();
141+
}
142+
143+
}

0 commit comments

Comments
 (0)