├── .gitignore
├── AndroidManifest.xml
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libs
├── android-support-v4.jar
└── baasbox-android-0.7.3.jar
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── layout
│ ├── activity_diary_details.xml
│ ├── activity_diary_list.xml
│ ├── activity_diary_panes.xml
│ ├── activity_edit_list.xml
│ ├── activity_login.xml
│ ├── add_diary_note.xml
│ └── fragment_diary_details.xml
├── menu
│ ├── add_note.xml
│ ├── login.xml
│ └── main.xml
├── values-large
│ ├── refs.xml
│ └── styles.xml
├── values-sw600dp
│ └── refs.xml
└── values
│ ├── attrs.xml
│ ├── dimen.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── baasbox
└── deardiary
├── DearDiary.java
└── ui
├── AddNoteFragment.java
├── EditActivity.java
├── LoginActivity.java
├── NoteDetailsFragment.java
├── NoteListActivity.java
├── NotesAdapter.java
├── NotesDetailsActivity.java
└── NotesListFragment.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | .idea
4 | *.iml
5 | .DS_Store
6 | .classpath
7 | .project
8 | .settings/*
9 | bin/**
10 | build/**
11 | gen/**
12 | project.properties
13 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
32 |
33 |
34 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dear Diary BaasBox Sample
2 |
3 | BaasBox is a tool that allows you to quickly build a back end for your app.
4 | You can install it on your local machine (ideal for development and testing) or your own server.
5 | It comes with an SDK that simplifies the integration of your Android app with the server.
6 | In this tutorial you will learn how to integrate an existing Android application with BaasBox.
7 |
8 | To complete this walk through you need a working copy of the Android SDK.
9 | You can download the starter project from [DearDiary-Android-Starter]().
10 |
11 | Unzip and run the project to see if it works as expected, it's a simple personal diary
12 | composed of three activities, a list of your notes, the details, and an activity to add
13 | new notes to the diary.
14 |
15 | Even though this pretty simple app works, it has a big shortcoming, if you uninstall it from your
16 | device, you will loose all your notes, and there is no way to restore them.
17 |
18 | Wouldn’t it be cool if we could save them on a back end? That’s exactly what we are going to do in this tutorial.
19 |
20 | ## Installing BaasBox
21 |
22 | The first step is to install BaasBox. For sake of simplicity we will show how to install it on a local machine. You will see that’s very easy. Download the latest version of BaasBox from here. Unzip the file, open Terminal, go to the directory unzipped, type “./start” and hit return. BaasBox is now running on your local machine. To test visit the following link: **http://localhost:9000/** and you should see the following screen.
23 |
24 |
25 | ## Importing the sdk
26 | If you are on eclipse you can download the sdk from [here](). Put the jar in to your libs folder
27 | and you are ready to go.
28 | Using gradle is even simpler you just need to add the following line to your dependencies
29 |
30 | ```groovy
31 | compile 'com.baasbox:baasbox-android:0.7.3-alpha'
32 | ```
33 | After refreshing your ide, you should be able to use the sdk classes in your project
34 |
35 | ## Setup the client library
36 | The BaasBox service could be installed anywhere on the web
37 | so you probably need to configure it a bit.
38 | We suggest to initialize the client in your
39 | *Application* onCreate method.
40 | The starter project includes an empty DearDiary class.
41 | Open the java file and add the following lines:
42 | ```java
43 |
44 | private BaasBox box;
45 |
46 | @Override
47 | public void onCreate() {
48 | super.onCreate();
49 | BaasBox.Config config = new BaasBox.Config();
50 | config.API_DOMAIN = "10.0.0.2"; // the host address
51 | config.APP_CODE = "1234567890"; // your appcode
52 | config.HTTP_PORT = 9000; // your port
53 |
54 | box = BaasBox.initDefault(this,config);
55 | }
56 | ```
57 |
58 | Also don't forget to add the required internet permissions
59 | to your manifest:
60 |
61 | ```xml
62 |
63 | ```
64 |
65 | After all you are going to connect to a backend!!!
66 |
67 | With this setup you are ready to use the sdk in your app.
68 | Don't forget to customize the configuration to adapt it to your environment.
69 |
70 | ## Authenticate with the server
71 | BaasBox provides means for authenticatication, so that different user
72 | can be distinguished on the backed.
73 | The sample project includes a barebone LoginActivity, we are going to integrate it in
74 | the app.
75 |
76 | The first thing to do is to check if there is alrady an an authenticated user for this device.
77 | Open the NoteListActivity file and right at the start of onCreate, where is the *todo 1* mark
78 | add the following lines.
79 |
80 | ```java
81 | if (BaasUser.current() == null){
82 | startLoginScreen();
83 | return;
84 | }
85 | ```
86 |
87 | BaasBox sdk remembers the currently logged in user.
88 | ```java BaasUser.current() ``` will return the current one
89 | or null if no one is logged in, in this case we will start the login screen.
90 |
91 | Now in the LoginActivity search for the two todo items for you.
92 | This is your first call to BaasBox:
93 |
94 | ```java
95 | private void signupWithBaasBox(boolean newUser){
96 | //todo 3.1
97 | BaasUser user = BaasUser.withUserName(mUsername);
98 | user.setPassword(mPassword);
99 | if (newUser) {
100 | user.signup(onComplete);
101 | } else {
102 | user.login(onComplete);
103 | }
104 | }
105 | //todo 3.2
106 | private final BaasHandler onComplete =
107 | new BaasHandler() {
108 | @Override
109 | public void handle(BaasResult result) {
110 | if(result.isSuccess()){
111 | completeLogin(true);
112 | } else {
113 | Log.d(TAG,result.error().toString());
114 | completeLogin(false);
115 | }
116 | }
117 | };
118 | ```
119 |
120 | you can login or signup using methods of the BaasUser class,they obviously are
121 | *signup* and *login*.
122 | You obtain an instance of a user through the factory method:
123 | ```java
124 | BaasUser.withUserName(...);
125 | ```
126 |
127 | These methods are executed asynchronously so you need to pass
128 | a callback to be invoked upon completion, in this case the **onComplete**
129 | variable. The callback will receive the result of the rest api call, or possibly
130 | an error you can inspect docs of the methods of BaasResult to see how it works in details.
131 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | mavenCentral()
6 |
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:0.12.+'
10 | }
11 | }
12 |
13 | task wrapper(type: Wrapper) {
14 | gradleVersion = '1.10'
15 | }
16 |
17 | apply plugin: 'android'
18 |
19 | repositories {
20 | mavenCentral()
21 | }
22 |
23 | android {
24 | compileSdkVersion 19
25 | buildToolsVersion "19.1.0"
26 | sourceSets {
27 | main{
28 | manifest.srcFile 'AndroidManifest.xml'
29 | java.srcDirs = ['src']
30 | resources.srcDirs = ['src']
31 | aidl.srcDirs = ['src']
32 | renderscript.srcDirs = ['src']
33 | res.srcDirs = ['res']
34 | assets.srcDirs = ['assets']
35 | }
36 | }
37 | }
38 |
39 | dependencies {
40 | compile 'com.android.support:support-v4:19.1.0'
41 | compile 'com.android.support:appcompat-v7:19.1.0'
42 | compile 'com.baasbox:baasbox-android:0.8.+'
43 | }
44 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jan 28 09:45:04 CET 2014
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/libs/baasbox-android-0.7.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/libs/baasbox-android-0.7.3.jar
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baasbox/DearDiary-Android/0a6af798065e15e84742d804fad954523de7fd5e/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/activity_diary_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/layout/activity_diary_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/layout/activity_diary_panes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
19 |
20 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/res/layout/activity_edit_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
13 |
17 |
25 |
26 |
27 |
28 |
32 |
33 |
35 |
36 |
44 |
45 |
56 |
57 |
58 |
66 |
67 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/res/layout/add_diary_note.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
12 |
20 |
--------------------------------------------------------------------------------
/res/layout/fragment_diary_details.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
15 |
19 |
25 |
26 |
34 |
35 |
--------------------------------------------------------------------------------
/res/menu/add_note.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/res/menu/login.xml:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/res/values-large/refs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | - @layout/activity_diary_panes
4 |
--------------------------------------------------------------------------------
/res/values-large/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-sw600dp/refs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | - @layout/activity_diary_panes
4 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/res/values/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Dear Diary
3 | Sign in
4 |
5 |
6 | Username
7 | Password
8 |
9 | Sign in or register
10 | Sign in
11 |
12 | Recover lost password
13 |
14 | Signing in…
15 |
16 | This email address is invalid
17 | This password is too short
18 | This password is incorrect
19 | This field is required
20 |
21 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/DearDiary.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 | import com.baasbox.android.*;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by Andrea Tortorella on 24/01/14.
11 | */
12 | public class DearDiary extends Application {
13 |
14 | @Override
15 | public void onCreate() {
16 | super.onCreate();
17 | //todo 1.2
18 | BaasBox.builder(this).setAuthentication(BaasBox.Config.AuthType.SESSION_TOKEN)
19 | .setApiDomain("10.0.2.0")
20 | .setPort(9000)
21 | .setAppCode("1234567890")
22 | .init();
23 | // BaasBox.Config config = new BaasBox.Config();
24 | // config.authenticationType= BaasBox.Config.AuthType.SESSION_TOKEN;
25 | // config.apiDomain = "192.168.56.1"; // the host address
26 | // config.httpPort=9000;
27 | // BaasBox.initDefault(this,config);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/AddNoteFragment.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.app.Dialog;
6 | import android.content.DialogInterface;
7 | import android.content.res.TypedArray;
8 | import android.os.Bundle;
9 | import android.support.v4.app.DialogFragment;
10 | import android.util.AttributeSet;
11 | import android.view.*;
12 | import android.widget.EditText;
13 | import com.baasbox.android.BaasDocument;
14 | import com.baasbox.deardiary.R;
15 |
16 | /**
17 | * Created by Andrea Tortorella on 24/01/14.
18 | */
19 | public class AddNoteFragment extends DialogFragment {
20 |
21 | private EditText mTitle;
22 | private EditText mContent;
23 | private boolean mShowAsDialog;
24 |
25 | public interface OnAddNote {
26 | public void onAddNote(BaasDocument values);
27 | }
28 |
29 | private OnAddNote mListener;
30 |
31 | private final static OnAddNote NOOP = new OnAddNote() {
32 | @Override
33 | public void onAddNote(BaasDocument values) {
34 | }
35 | };
36 |
37 | @Override
38 | public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
39 | super.onInflate(activity, attrs, savedInstanceState);
40 | TypedArray a = activity.obtainStyledAttributes(attrs,R.styleable.AddNoteFragment);
41 | mShowAsDialog =a.getBoolean(R.styleable.AddNoteFragment_showAsDialog,true);
42 | a.recycle();
43 | }
44 |
45 | @Override
46 | public void onAttach(Activity activity) {
47 | super.onAttach(activity);
48 | if (activity instanceof OnAddNote){
49 | mListener = (OnAddNote)activity;
50 | } else {
51 | mListener = NOOP;
52 | }
53 | }
54 |
55 | @Override
56 | public void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 | setShowsDialog(mShowAsDialog);
59 | }
60 |
61 |
62 | @Override
63 | public void onDetach() {
64 | super.onDetach();
65 | mListener = NOOP;
66 | }
67 |
68 |
69 | @Override
70 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
71 | View v = loadView(inflater, null);
72 | return v;
73 | }
74 |
75 | private View loadView(LayoutInflater inflater, ViewGroup container) {
76 | View v = inflater.inflate(R.layout.add_diary_note,container,false);
77 | mTitle = (EditText)v.findViewById(R.id.in_title);
78 | mContent = (EditText)v.findViewById(R.id.in_content);
79 | return v;
80 | }
81 |
82 | @Override
83 | public Dialog onCreateDialog(Bundle savedInstanceState) {
84 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
85 | View v=loadView(LayoutInflater.from(getActivity()), null);
86 | builder.setView(v)
87 | .setTitle("Add note")
88 | .setPositiveButton(getString(android.R.string.ok), fOk)
89 | .setNegativeButton(getString(android.R.string.cancel),null);
90 | return builder.create();
91 | }
92 |
93 |
94 | public BaasDocument getData() {
95 | String title = mTitle.getText().toString();
96 | String content = mContent.getText().toString();
97 | BaasDocument doc = new BaasDocument("memos");
98 | doc.putString("title",title);
99 | doc.putString("content",content);
100 | return doc;
101 | }
102 |
103 | private void dispatchAddNote(){
104 | mListener.onAddNote(getData());
105 | }
106 |
107 | private final DialogInterface.OnClickListener fOk = new DialogInterface.OnClickListener() {
108 | @Override
109 | public void onClick(DialogInterface dialog, int which) {
110 | dispatchAddNote();
111 | }
112 | };
113 | }
114 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/EditActivity.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.app.Activity;
4 | import android.app.ProgressDialog;
5 | import android.os.Bundle;
6 | import android.support.v7.app.ActionBarActivity;
7 | import android.util.Log;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.widget.Toast;
11 | import com.baasbox.android.*;
12 | import com.baasbox.deardiary.R;
13 |
14 | /**
15 | * Created by Andrea Tortorella on 24/01/14.
16 | */
17 | public class EditActivity extends ActionBarActivity {
18 | //todo
19 | private static final String PENDING_SAVE = "PENDING_SAVE";
20 | public static final int RESULT_SESSION_EXPIRED = Activity.RESULT_FIRST_USER+1;
21 | public static final int RESULT_FAILED = RESULT_SESSION_EXPIRED+1;
22 |
23 |
24 | private AddNoteFragment mAddNotes;
25 |
26 | //todo
27 | private RequestToken mAddToken;
28 | private ProgressDialog mDialog;
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_edit_list);
34 | mDialog = new ProgressDialog(this);
35 | mDialog.setMessage("Uploading...");
36 | mAddNotes = (AddNoteFragment)getSupportFragmentManager().findFragmentById(R.id.Edit);
37 | if (savedInstanceState!=null){
38 | mAddToken = RequestToken.loadAndResume(savedInstanceState,PENDING_SAVE,uploadHandler);
39 | if(mAddToken!=null){
40 | mDialog.show();
41 | }
42 | }
43 | }
44 |
45 | @Override
46 | protected void onResume() {
47 | super.onResume();
48 | }
49 |
50 | @Override
51 | protected void onPause() {
52 | super.onPause();
53 | }
54 |
55 | @Override
56 | protected void onSaveInstanceState(Bundle outState) {
57 | super.onSaveInstanceState(outState);
58 |
59 | if (mAddToken!=null){
60 | mAddToken.suspendAndSave(outState,PENDING_SAVE);
61 | mDialog.dismiss();
62 | }
63 | }
64 |
65 | @Override
66 | public boolean onCreateOptionsMenu(Menu menu) {
67 | getMenuInflater().inflate(R.menu.add_note, menu);
68 | return true;
69 | }
70 |
71 | @Override
72 | public boolean onOptionsItemSelected(MenuItem item) {
73 | if (item.getItemId()==R.id.add_note_action){
74 | saveOnBaasBox(mAddNotes.getData());
75 | return true;
76 | }
77 | return super.onOptionsItemSelected(item);
78 | }
79 |
80 |
81 | private void saveOnBaasBox(BaasDocument document){
82 | mDialog.show();
83 | mAddToken=document.save(SaveMode.IGNORE_VERSION,uploadHandler);
84 | }
85 |
86 | private final BaasHandler uploadHandler = new BaasHandler() {
87 | @Override
88 | public void handle(BaasResult doc) {
89 | mDialog.dismiss();
90 | mAddToken=null;
91 |
92 | if(doc.isSuccess()){
93 | setResult(RESULT_OK);
94 | finish();
95 | } else {
96 | if (doc.error() instanceof BaasInvalidSessionException){
97 | setResult(RESULT_SESSION_EXPIRED);
98 | finish();
99 | }else{
100 | setResult(RESULT_FAILED);
101 | Log.d("ERROR","Failed with error",doc.error());
102 | }
103 | }
104 | }
105 | };
106 | }
107 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.annotation.TargetApi;
6 | import android.app.ProgressDialog;
7 | import android.content.Intent;
8 | import android.os.Build;
9 | import android.os.Bundle;
10 | import android.support.v4.app.FragmentActivity;
11 | import android.text.TextUtils;
12 | import android.util.Log;
13 | import android.view.KeyEvent;
14 | import android.view.Menu;
15 | import android.view.View;
16 | import android.view.inputmethod.EditorInfo;
17 | import android.widget.EditText;
18 | import android.widget.TextView;
19 | import com.baasbox.android.BaasHandler;
20 | import com.baasbox.android.BaasResult;
21 | import com.baasbox.android.BaasUser;
22 | import com.baasbox.android.RequestToken;
23 | import com.baasbox.deardiary.R;
24 |
25 | /**
26 | * Created by Andrea Tortorella on 24/01/14.
27 | */
28 | public class LoginActivity extends FragmentActivity {
29 | private final static String SIGNUP_TOKEN_KEY = "signup_token_key";
30 | public static final String EXTRA_USERNAME = "com.baasbox.deardiary.username.EXTRA";
31 |
32 | private String mUsername;
33 | private String mPassword;
34 |
35 | private EditText mUserView;
36 | private EditText mPasswordView;
37 | private View mLoginFormView;
38 | private View mLoginStatusView;
39 | private TextView mLoginStatusMessageView;
40 |
41 |
42 |
43 | private RequestToken mSignupOrLogin;
44 |
45 | @Override
46 | protected void onCreate(Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | setContentView(R.layout.activity_login);
49 |
50 | if (savedInstanceState!=null){
51 | mSignupOrLogin = savedInstanceState.getParcelable(SIGNUP_TOKEN_KEY);
52 | }
53 |
54 | mUsername = getIntent().getStringExtra(EXTRA_USERNAME);
55 | mUserView = (EditText) findViewById(R.id.email);
56 | mUserView.setText(mUsername);
57 | mLoginStatusView = findViewById(R.id.login_status);
58 | mLoginFormView = findViewById(R.id.login_form);
59 | mLoginStatusMessageView = (TextView)findViewById(R.id.login_status_message);
60 | mPasswordView = (EditText) findViewById(R.id.password);
61 | mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
62 | @Override
63 | public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
64 | if (id == R.id.login || id == EditorInfo.IME_NULL) {
65 | attemptLogin(false);
66 | return true;
67 | }
68 | return false;
69 | }
70 | });
71 |
72 | findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
73 | @Override
74 | public void onClick(View v) {
75 | attemptLogin(true);
76 | }
77 | });
78 |
79 | findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener(){
80 | @Override
81 | public void onClick(View v) {
82 | attemptLogin(false);
83 | }
84 | });
85 | }
86 |
87 | @Override
88 | protected void onPause() {
89 | super.onPause();
90 | if (mSignupOrLogin!=null){
91 | showProgress(false);
92 | mSignupOrLogin.suspend();
93 | }
94 | }
95 |
96 | @Override
97 | protected void onResume() {
98 | super.onResume();
99 | if (mSignupOrLogin!=null){
100 | showProgress(true);
101 | mSignupOrLogin.resume(onComplete);
102 | }
103 | }
104 |
105 | @Override
106 | protected void onSaveInstanceState(Bundle outState) {
107 | super.onSaveInstanceState(outState);
108 | if (mSignupOrLogin!=null){
109 | outState.putParcelable(SIGNUP_TOKEN_KEY,mSignupOrLogin);
110 | }
111 | }
112 |
113 | private void completeLogin(boolean success){
114 | showProgress(false);
115 | mSignupOrLogin = null;
116 | if (success) {
117 | Intent intent = new Intent(this,NoteListActivity.class);
118 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
119 | startActivity(intent);
120 | finish();
121 | } else {
122 | mPasswordView.setError(getString(R.string.error_incorrect_password));
123 | mPasswordView.requestFocus();
124 | }
125 | }
126 |
127 | @Override
128 | public boolean onCreateOptionsMenu(Menu menu) {
129 | super.onCreateOptionsMenu(menu);
130 | getMenuInflater().inflate(R.menu.login, menu);
131 | return true;
132 | }
133 |
134 | public void attemptLogin(boolean newUser) {
135 | // Reset errors.
136 | mUserView.setError(null);
137 | mPasswordView.setError(null);
138 |
139 | // Store values at the time of the login attempt.
140 | mUsername = mUserView.getText().toString();
141 | mPassword = mPasswordView.getText().toString();
142 |
143 | boolean cancel = false;
144 | View focusView = null;
145 |
146 | // Check for a valid password.
147 | if (TextUtils.isEmpty(mPassword)) {
148 | mPasswordView.setError(getString(R.string.error_field_required));
149 | focusView = mPasswordView;
150 | cancel = true;
151 | } else if (mPassword.length() < 4) {
152 | mPasswordView.setError(getString(R.string.error_invalid_password));
153 | focusView = mPasswordView;
154 | cancel = true;
155 | }
156 |
157 | // Check for a valid email address.
158 | if (TextUtils.isEmpty(mUsername)) {
159 | mUserView.setError(getString(R.string.error_field_required));
160 | focusView = mUserView;
161 | cancel = true;
162 | }
163 |
164 | if (cancel) {
165 | // There was an error; don't attempt login and focus the first
166 | // form field with an error.
167 | focusView.requestFocus();
168 | } else {
169 | // Show a progress spinner, and kick off a background task to
170 | // perform the user login attempt.
171 | mLoginStatusMessageView.setText(R.string.login_progress_signing_in);
172 | showProgress(true);
173 | signupWithBaasBox(newUser);
174 | }
175 | }
176 |
177 | private void signupWithBaasBox(boolean newUser){
178 | //todo 3.1
179 | BaasUser user = BaasUser.withUserName(mUsername);
180 | user.setPassword(mPassword);
181 | if (newUser) {
182 | mSignupOrLogin=user.signup(onComplete);
183 | } else {
184 | mSignupOrLogin=user.login(onComplete);
185 | }
186 | }
187 |
188 | //todo 3.2
189 | private final BaasHandler onComplete =
190 | new BaasHandler() {
191 | @Override
192 | public void handle(BaasResult result) {
193 |
194 | mSignupOrLogin = null;
195 | if (result.isFailed()){
196 | Log.d("ERROR","ERROR",result.error());
197 | }
198 | completeLogin(result.isSuccess());
199 | }
200 | };
201 |
202 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
203 | private void showProgress(final boolean show) {
204 | // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
205 | // for very easy animations. If available, use these APIs to fade-in
206 | // the progress spinner.
207 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
208 | int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
209 |
210 | mLoginStatusView.setVisibility(View.VISIBLE);
211 | mLoginStatusView.animate()
212 | .setDuration(shortAnimTime)
213 | .alpha(show ? 1 : 0)
214 | .setListener(new AnimatorListenerAdapter() {
215 | @Override
216 | public void onAnimationEnd(Animator animation) {
217 | mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
218 | }
219 | });
220 |
221 | mLoginFormView.setVisibility(View.VISIBLE);
222 | mLoginFormView.animate()
223 | .setDuration(shortAnimTime)
224 | .alpha(show ? 0 : 1)
225 | .setListener(new AnimatorListenerAdapter() {
226 | @Override
227 | public void onAnimationEnd(Animator animation) {
228 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
229 | }
230 | });
231 | } else {
232 | // The ViewPropertyAnimator APIs are not available, so simply show
233 | // and hide the relevant UI components.
234 | mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
235 | mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
236 | }
237 | }
238 |
239 | }
240 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/NoteDetailsFragment.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 | import com.baasbox.android.BaasDocument;
10 | import com.baasbox.deardiary.R;
11 |
12 |
13 | /**
14 | * Created by Andrea Tortorella on 24/01/14.
15 | */
16 | public class NoteDetailsFragment extends Fragment {
17 |
18 | static final String CURRENTLY_SHOWN_ITEM_KEY = "currently_shown_item";
19 |
20 | private BaasDocument mNote;
21 |
22 | private TextView mTitleView;
23 | private TextView mContentView;
24 | private TextView mDateView;
25 |
26 | @Override
27 | public void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | if (getArguments().containsKey(CURRENTLY_SHOWN_ITEM_KEY)){
30 | mNote = getArguments().getParcelable(CURRENTLY_SHOWN_ITEM_KEY);
31 | }
32 | }
33 |
34 | @Override
35 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
36 | View root = inflater.inflate(R.layout.fragment_diary_details,container,false);
37 | mTitleView = (TextView) root.findViewById(R.id.tv_diary_note_title);
38 | mContentView = (TextView) root.findViewById(R.id.tv_diary_note_content);
39 | mDateView = (TextView) root.findViewById(R.id.tv_diary_note_date);
40 | refreshViews();
41 | return root;
42 | }
43 |
44 | private void refreshViews(){
45 | if (mNote!=null) {
46 | mTitleView.setText(mNote.getString("title"));
47 | mContentView.setText(mNote.getString("content"));
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/NoteListActivity.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.ActionBarActivity;
7 | import android.util.Log;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.widget.Toast;
11 | import com.baasbox.android.*;
12 | import com.baasbox.deardiary.R;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by Andrea Tortorella on 24/01/14.
18 | */
19 | public class NoteListActivity extends ActionBarActivity
20 | implements NotesListFragment.Callbacks,AddNoteFragment.OnAddNote {
21 | private final static String REFRESH_TOKEN_KEY = "refresh";
22 | private final static String SAVING_TOKEN_KEY = "saving";
23 | private final static String LOGOUT_TOKEN_KEY = "logout";
24 |
25 | private final static int EDIT_CODE = 1;
26 |
27 | private boolean mUseTwoPane;
28 | private NotesListFragment mListFragment;
29 | private RequestToken mRefresh;
30 | private RequestToken mSaving;
31 |
32 | private ProgressDialog mDialog;
33 | private boolean mDoRefresh=false;
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | //todo 2
39 | if (BaasUser.current() == null){
40 | startLoginScreen();
41 | return;
42 | }
43 |
44 | mDialog = new ProgressDialog(this);
45 | mDialog.setMessage("Refreshing...");
46 |
47 | if (savedInstanceState!=null){
48 | mRefresh = RequestToken.loadAndResume(savedInstanceState,REFRESH_TOKEN_KEY,onRefresh);
49 | mSaving = RequestToken.loadAndResume(savedInstanceState,SAVING_TOKEN_KEY,onSave);
50 | logoutToken = RequestToken.loadAndResume(savedInstanceState,LOGOUT_TOKEN_KEY,logoutHandler);
51 | }
52 |
53 | if (mSaving!=null||mRefresh!=null||logoutToken!=null){
54 | mDialog.show();
55 | }
56 | mDoRefresh = savedInstanceState==null;
57 |
58 | setContentView(R.layout.activity_diary_list);
59 |
60 | mListFragment = (NotesListFragment)getSupportFragmentManager().findFragmentById(R.id.ItemList);
61 |
62 | if (findViewById(R.id.fragment_host) != null) {
63 | mUseTwoPane = true;
64 | mListFragment.setActivateOnItemClick(true);
65 | }
66 | }
67 |
68 | @Override
69 | protected void onResume() {
70 | super.onResume();
71 | if(mRefresh==null&&mDoRefresh){
72 | refreshDocuments();
73 | }
74 | }
75 |
76 | @Override
77 | protected void onPause() {
78 | super.onPause();
79 | if (mDialog.isShowing()){
80 | mDialog.dismiss();
81 | }
82 |
83 | }
84 |
85 | @Override
86 | protected void onSaveInstanceState(Bundle outState) {
87 | super.onSaveInstanceState(outState);
88 | if (mRefresh!=null){
89 | mRefresh.suspendAndSave(outState,REFRESH_TOKEN_KEY);
90 | }
91 | if (mSaving!=null){
92 | mSaving.suspendAndSave(outState,SAVING_TOKEN_KEY);
93 | }
94 | if (logoutToken!=null){
95 | mSaving.suspendAndSave(outState,LOGOUT_TOKEN_KEY);
96 | }
97 | }
98 |
99 | private void startLoginScreen(){
100 | mDoRefresh = false;
101 | Intent intent = new Intent(this,LoginActivity.class);
102 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
103 | startActivity(intent);
104 | finish();
105 | }
106 | @Override
107 | public boolean onCreateOptionsMenu(Menu menu) {
108 | getMenuInflater().inflate(R.menu.main,menu);
109 | return super.onCreateOptionsMenu(menu);
110 | }
111 |
112 | @Override
113 | public boolean onOptionsItemSelected(MenuItem item) {
114 | if (item.getItemId()==R.id.add_action){
115 | if (mUseTwoPane){
116 | getSupportFragmentManager()
117 | .beginTransaction()
118 | .replace(R.id.fragment_host,new AddNoteFragment())
119 | .addToBackStack(null)
120 | .commit();
121 | } else {
122 | Intent intent = new Intent(this,EditActivity.class);
123 | startActivityForResult(intent,EDIT_CODE);
124 | }
125 | return true;
126 | } else if (item.getItemId()==R.id.logout_action){
127 | BaasUser.current().logout(logoutHandler);
128 | return true;
129 | }
130 | return super.onOptionsItemSelected(item);
131 | }
132 |
133 | private void onLogout(){
134 | startLoginScreen();
135 | }
136 |
137 | private RequestToken logoutToken;
138 | private final BaasHandler logoutHandler =
139 | new BaasHandler() {
140 | @Override
141 | public void handle(BaasResult voidBaasResult) {
142 | logoutToken=null;
143 | onLogout();
144 | }
145 | };
146 | @Override
147 | public void onItemSelected(BaasDocument document) {
148 | if (mUseTwoPane) {
149 | Bundle args = new Bundle();
150 | args.putParcelable(NoteDetailsFragment.CURRENTLY_SHOWN_ITEM_KEY, document);
151 | NoteDetailsFragment fragment = new NoteDetailsFragment();
152 | fragment.setArguments(args);
153 | getSupportFragmentManager().beginTransaction()
154 | .replace(R.id.fragment_host,fragment)
155 | .commit();
156 | } else {
157 | Intent details = new Intent(this,NotesDetailsActivity.class);
158 | details.putExtra(NoteDetailsFragment.CURRENTLY_SHOWN_ITEM_KEY,document);
159 | startActivity(details);
160 | }
161 | }
162 |
163 | @Override
164 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
165 | if (requestCode==EDIT_CODE){
166 | if (resultCode==RESULT_OK){
167 | refreshDocuments();
168 | } else if(resultCode==EditActivity.RESULT_SESSION_EXPIRED){
169 | startLoginScreen();
170 | } else if (resultCode==EditActivity.RESULT_FAILED){
171 | Toast.makeText(this,"Failed to add note",Toast.LENGTH_LONG).show();
172 | }
173 | }else {
174 | super.onActivityResult(requestCode, resultCode, data);
175 | }
176 | }
177 |
178 | private void refreshDocuments(){
179 | if(!mDialog.isShowing())mDialog.show();
180 | mRefresh =BaasDocument.fetchAll("memos",onRefresh);
181 | }
182 |
183 | private final BaasHandler>
184 | onRefresh = new BaasHandler>() {
185 | @Override
186 | public void handle(BaasResult> result) {
187 | mDialog.dismiss();
188 | mRefresh=null;
189 | try {
190 | mListFragment.refresh(result.get());
191 | }catch (BaasInvalidSessionException e){
192 | startLoginScreen();
193 | }catch (BaasException e){
194 | Log.e("LOGERR","Error "+e.getMessage(),e);
195 | Toast.makeText(NoteListActivity.this,"Error while talking with the box",Toast.LENGTH_LONG).show();
196 | }
197 | }
198 | };
199 |
200 | @Override
201 | public void onAddNote(BaasDocument document) {
202 | mDialog.show();
203 | mSaving =document.save(SaveMode.IGNORE_VERSION,onSave);
204 | }
205 |
206 | private final BaasHandler onSave =
207 | new BaasHandler() {
208 | @Override
209 | public void handle(BaasResult baasDocumentBaasResult) {
210 | mSaving=null;
211 | mDialog.dismiss();
212 | refreshDocuments();
213 | }
214 | };
215 | }
216 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/NotesAdapter.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 | import com.baasbox.android.BaasDocument;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * Created by Andrea Tortorella on 24/01/14.
15 | */
16 | class NotesAdapter extends BaseAdapter {
17 |
18 | private List mDocuments;
19 | private LayoutInflater mInflater;
20 |
21 | NotesAdapter(Context context,List documents){
22 | this.mDocuments=documents;
23 | mInflater = LayoutInflater.from(context);
24 | }
25 |
26 | @Override
27 | public int getCount() {
28 | if (mDocuments==null){
29 | return 0;
30 | }
31 | return mDocuments.size();
32 | }
33 |
34 | @Override
35 | public BaasDocument getItem(int position) {
36 | return mDocuments.get(position);
37 | }
38 |
39 | @Override
40 | public long getItemId(int position) {
41 | return position;
42 | }
43 |
44 | @Override
45 | public View getView(int position, View convertView, ViewGroup parent) {
46 | ViewHolder h;
47 | if (convertView==null){
48 | convertView = mInflater.inflate(android.R.layout.simple_list_item_2,parent,false);
49 | h = new ViewHolder();
50 | h.text1 = (TextView)convertView.findViewById(android.R.id.text1);
51 | h.text2 = (TextView)convertView.findViewById(android.R.id.text2);
52 | convertView.setTag(h);
53 | } else {
54 | h = (ViewHolder)convertView.getTag();
55 | }
56 | BaasDocument document = mDocuments.get(position);
57 | String title = document.getString("title");
58 | String creationDate = document.getCreationDate();
59 | h.text1.setText(title);
60 | h.text2.setText(creationDate);
61 | return convertView;
62 | }
63 |
64 | private static class ViewHolder{
65 | private TextView text1;
66 | private TextView text2;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/NotesDetailsActivity.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v4.app.NavUtils;
6 | import android.support.v7.app.ActionBarActivity;
7 | import android.view.MenuItem;
8 | import com.baasbox.deardiary.R;
9 |
10 | /**
11 | * Created by Andrea Tortorella on 24/01/14.
12 | */
13 | public class NotesDetailsActivity extends ActionBarActivity {
14 |
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setContentView(R.layout.activity_diary_details);
19 |
20 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
21 |
22 | if (savedInstanceState == null) {
23 | Bundle args = new Bundle();
24 | args.putParcelable(NoteDetailsFragment.CURRENTLY_SHOWN_ITEM_KEY,
25 | getIntent().getParcelableExtra(NoteDetailsFragment.CURRENTLY_SHOWN_ITEM_KEY));
26 | NoteDetailsFragment fragment = new NoteDetailsFragment();
27 | fragment.setArguments(args);
28 | getSupportFragmentManager().beginTransaction()
29 | .add(R.id.fragment_host,fragment)
30 | .commit();
31 | }
32 | }
33 |
34 | @Override
35 | public boolean onOptionsItemSelected(MenuItem item) {
36 | int id = item.getItemId();
37 | if (id == android.R.id.home) {
38 | NavUtils.navigateUpTo(this,new Intent(this,NoteListActivity.class));
39 | return true;
40 | }
41 | return super.onOptionsItemSelected(item);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/baasbox/deardiary/ui/NotesListFragment.java:
--------------------------------------------------------------------------------
1 | package com.baasbox.deardiary.ui;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.support.v4.app.ListFragment;
6 | import android.view.View;
7 | import android.widget.ListView;
8 | import com.baasbox.android.BaasDocument;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | *
15 | * Created by Andrea Tortorella on 24/01/14.
16 | */
17 | public class NotesListFragment extends ListFragment {
18 |
19 | private final static String CURRENTLY_SELECTED_ITEM_KEY = "currently_selected_item";
20 | private final static String SAVED_DOCS = "saved_docs";
21 |
22 | public void refresh(List docs) {
23 | mDocuments.clear();
24 | mDocuments.addAll(docs);
25 | getListAdapter().notifyDataSetChanged();
26 | }
27 |
28 | public interface Callbacks {
29 | public void onItemSelected(BaasDocument document);
30 | }
31 |
32 | private final static Callbacks sNoopCallbacks = new Callbacks() {
33 | @Override
34 | public void onItemSelected(BaasDocument document) {
35 | }
36 | };
37 |
38 | private int mSelectedPostion = ListView.INVALID_POSITION;
39 |
40 | private Callbacks mCallbacks;
41 | private NotesAdapter mAdapter;
42 | private ArrayList mDocuments;
43 |
44 | @Override
45 | public void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | if (savedInstanceState==null){
48 | mDocuments = new ArrayList();
49 | } else {
50 | mDocuments = savedInstanceState.getParcelableArrayList(SAVED_DOCS);
51 | }
52 | mAdapter = new NotesAdapter(getActivity(),mDocuments);
53 | setListAdapter(mAdapter);
54 | }
55 |
56 | @Override
57 | public void onViewCreated(View view, Bundle savedInstanceState) {
58 | super.onViewCreated(view, savedInstanceState);
59 | if (savedInstanceState != null
60 | && savedInstanceState.containsKey(CURRENTLY_SELECTED_ITEM_KEY))
61 | setActivatedPosition(savedInstanceState.getInt(CURRENTLY_SELECTED_ITEM_KEY));
62 | }
63 |
64 | @Override
65 | public void onAttach(Activity activity) {
66 | super.onAttach(activity);
67 | if (!(activity instanceof Callbacks)) {
68 | throw new IllegalStateException("Activity must implement fragment's callbacks");
69 | }
70 | mCallbacks = (Callbacks)activity;
71 | }
72 |
73 | @Override
74 | public void onDetach() {
75 | super.onDetach();
76 | mCallbacks = sNoopCallbacks;
77 | }
78 |
79 | @Override
80 | public void onSaveInstanceState(Bundle outState) {
81 | super.onSaveInstanceState(outState);
82 | if (mSelectedPostion!=ListView.INVALID_POSITION){
83 | outState.putInt(CURRENTLY_SELECTED_ITEM_KEY,mSelectedPostion);
84 | }
85 | outState.putParcelableArrayList(SAVED_DOCS,mDocuments);
86 |
87 | }
88 |
89 | public void setActivateOnItemClick(boolean activateOnItemClick){
90 | getListView().setChoiceMode(activateOnItemClick
91 | ? ListView.CHOICE_MODE_SINGLE
92 | : ListView.CHOICE_MODE_NONE);
93 | }
94 |
95 | @Override
96 | public NotesAdapter getListAdapter() {
97 | return (NotesAdapter)super.getListAdapter();
98 | }
99 |
100 | @Override
101 | public void onListItemClick(ListView l, View v, int position, long id) {
102 | super.onListItemClick(l, v, position, id);
103 | mCallbacks.onItemSelected(getListAdapter().getItem(position));
104 | }
105 |
106 | private void setActivatedPosition(int position) {
107 | if (position == ListView.INVALID_POSITION) {
108 | getListView().setItemChecked(mSelectedPostion,false);
109 | } else {
110 | getListView().setItemChecked(position,true);
111 | }
112 | mSelectedPostion = position;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------