├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── vcs.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
├── misc.xml
└── codeStyleSettings.xml
├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-hdpi
│ │ │ ├── ic_action_remove.png
│ │ │ ├── ic_action_upload.png
│ │ │ └── ic_action_download.png
│ │ ├── drawable-mdpi
│ │ │ ├── ic_action_remove.png
│ │ │ ├── ic_action_upload.png
│ │ │ └── ic_action_download.png
│ │ ├── drawable-xhdpi
│ │ │ ├── ic_action_remove.png
│ │ │ ├── ic_action_upload.png
│ │ │ └── ic_action_download.png
│ │ ├── drawable-xxhdpi
│ │ │ ├── ic_action_remove.png
│ │ │ ├── ic_action_upload.png
│ │ │ └── ic_action_download.png
│ │ ├── values
│ │ │ ├── styles.xml
│ │ │ ├── dimens.xml
│ │ │ └── strings.xml
│ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ └── menu
│ │ │ └── menu_main.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── spjanson
│ │ └── restdemo
│ │ ├── UT.java
│ │ ├── REST.java
│ │ └── MainActivity.java
├── proguard-rules.pro
├── build.gradle
└── app.iml
├── settings.gradle
├── readme.txt
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── RESTDemo.iml
├── gradlew.bat
└── gradlew
/.idea/.name:
--------------------------------------------------------------------------------
1 | RESTDemo
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/readme.txt
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-hdpi/ic_action_remove.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-hdpi/ic_action_upload.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-mdpi/ic_action_remove.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-mdpi/ic_action_upload.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-hdpi/ic_action_download.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_action_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-mdpi/ic_action_download.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xhdpi/ic_action_remove.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xhdpi/ic_action_upload.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xxhdpi/ic_action_remove.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xxhdpi/ic_action_upload.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_action_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xhdpi/ic_action_download.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seanpjanson/RESTDemo/HEAD/app/src/main/res/drawable-xxhdpi/ic_action_download.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\SeanASUS\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion '23.0.0'
6 |
7 | defaultConfig {
8 | applicationId "com.spjanson.restdemo"
9 | minSdkVersion 16
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 | // https://developers.google.com/android/guides/setup
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | compile 'com.android.support:appcompat-v7:23.0.1'
25 | compile 'com.google.android.gms:play-services-identity:8.1.0'
26 | compile 'com.google.apis:google-api-services-drive:v2-rev105-1.17.0-rc'
27 | compile 'com.google.api-client:google-api-client-android:1.20.0'
28 | compile 'com.google.http-client:google-http-client-gson:1.20.0'
29 | }
30 |
--------------------------------------------------------------------------------
/RESTDemo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
18 |
19 |
24 |
25 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RESTDemo
5 |
6 | \n\n
7 | 1/ UPLOAD (upload icon) uploads a text file to Google Drive, creating a simple tree
8 | directory structure in the process.\n
9 | The createTree() method allows for testing of different CRUD primitives (search,
10 | create folder, etc…) in the process.\n\n
11 | 2/ DOWNLOAD (download icon) scans the tree created by the createTree() method. If the
12 | object is a file, it\'s metadata is updated (description field), the content is
13 | downloaded.\n\n
14 | 3/ DELETE (X - delete icon) scans the tree created by the createTree() method and deletes
15 | all the files and folders in the process\n
16 |
17 |
18 |
19 | UPLOAD file
20 | DOWNLOAD all files
21 | DELETE all files
22 | Select Google Account…
23 |
24 | CHECK PackageName / SHA1\nin Developers Console!
25 | UNSPECIFIED GOOGLE DRIVE\nACCESS FAILURE!
26 | NO ACCOUNT SELECTED!
27 | ACCESS NOT AUTHORIZED!
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/spjanson/restdemo/UT.java:
--------------------------------------------------------------------------------
1 | package com.spjanson.restdemo;
2 | /**
3 | * Copyright 2015 Sean Janson. All Rights Reserved.
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 | * http://www.apache.org/licenses/LICENSE-2.0
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | import android.content.ContentValues;
16 | import android.content.Context;
17 | import android.content.SharedPreferences;
18 | import android.preference.PreferenceManager;
19 | import android.util.Log;
20 |
21 | import java.io.BufferedInputStream;
22 | import java.io.BufferedOutputStream;
23 | import java.io.ByteArrayOutputStream;
24 | import java.io.File;
25 | import java.io.FileOutputStream;
26 | import java.io.InputStream;
27 | import java.text.SimpleDateFormat;
28 | import java.util.Date;
29 | import java.util.Locale;
30 |
31 | final class UT { private UT() {}
32 |
33 | private static final String L_TAG = "_X_";
34 |
35 | static final String MYROOT = "DEMORoot";
36 | static final String MIME_TEXT = "text/plain";
37 | static final String MIME_FLDR = "application/vnd.google-apps.folder";
38 |
39 | static final String TITL = "titl";
40 | static final String GDID = "gdid";
41 | static final String MIME = "mime";
42 |
43 | private static final String TITL_FMT = "yyMMdd-HHmmss";
44 |
45 | private static SharedPreferences pfs;
46 | static Context acx;
47 | static void init(Context ctx) {
48 | acx = ctx.getApplicationContext();
49 | pfs = PreferenceManager.getDefaultSharedPreferences(acx);
50 | }
51 |
52 | static class AM { private AM(){}
53 | private static final String ACC_NAME = "account_name";
54 | private static String mEmail = null;
55 |
56 | static void setEmail(String email) {
57 | UT.pfs.edit().putString(ACC_NAME, (mEmail = email)).apply();
58 | }
59 | static String getEmail() {
60 | return mEmail != null ? mEmail : (mEmail = UT.pfs.getString(ACC_NAME, null));
61 | }
62 | }
63 |
64 | static ContentValues newCVs(String titl, String gdId, String mime) {
65 | ContentValues cv = new ContentValues();
66 | if (titl != null) cv.put(TITL, titl);
67 | if (gdId != null) cv.put(GDID, gdId);
68 | if (mime != null) cv.put(MIME, mime);
69 | return cv;
70 | }
71 |
72 | private static File cchFile(String flNm) {
73 | File cche = UT.acx.getExternalCacheDir();
74 | return (cche == null || flNm == null) ? null : new File(cche.getPath() + File.separator + flNm);
75 | }
76 | static File str2File(String str, String name) {
77 | if (str == null) return null;
78 | byte[] buf = str.getBytes();
79 | File fl = cchFile(name);
80 | if (fl == null) return null;
81 | BufferedOutputStream bs = null;
82 | try {
83 | bs = new BufferedOutputStream(new FileOutputStream(fl));
84 | bs.write(buf);
85 | } catch (Exception e) {
86 | le(e);
87 | } finally {
88 | if (bs != null) try {
89 | bs.close();
90 | } catch (Exception e) {
91 | le(e);
92 | }
93 | }
94 | return fl;
95 | }
96 | static byte[] is2Bytes(InputStream is) {
97 | byte[] buf = null;
98 | BufferedInputStream bufIS = null;
99 | if (is != null) try {
100 | ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
101 | bufIS = new BufferedInputStream(is);
102 | buf = new byte[4096];
103 | int cnt;
104 | while ((cnt = bufIS.read(buf)) >= 0) {
105 | byteBuffer.write(buf, 0, cnt);
106 | }
107 | buf = byteBuffer.size() > 0 ? byteBuffer.toByteArray() : null;
108 | } catch (Exception ignore) {}
109 | finally {
110 | try {
111 | if (bufIS != null) bufIS.close();
112 | } catch (Exception ignore) {}
113 | }
114 | return buf;
115 | }
116 |
117 | static String time2Titl(Long milis) { // time -> yymmdd-hhmmss
118 | Date dt = (milis == null) ? new Date() : (milis >= 0) ? new Date(milis) : null;
119 | return (dt == null) ? null : new SimpleDateFormat(TITL_FMT, Locale.US).format(dt);
120 | }
121 | static String titl2Month(String titl) {
122 | return titl == null ? null : ("20" + titl.substring(0, 2) + "-" + titl.substring(2, 4));
123 | }
124 |
125 | static void le(Throwable ex) { Log.e(L_TAG, Log.getStackTraceString(ex)); }
126 | static void lg(String msg) { Log.d(L_TAG, msg); }
127 | }
128 |
129 |
130 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/.idea/codeStyleSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | xmlns:android
80 | Namespace:
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | xmlns:.*
90 | Namespace:
91 |
92 |
93 | BY_NAME
94 |
95 |
96 |
97 |
98 |
99 |
100 | .*:id
101 | http://schemas.android.com/apk/res/android
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | .*:name
111 | http://schemas.android.com/apk/res/android
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | name
121 | ^$
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | style
131 | ^$
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | .*
141 | ^$
142 |
143 |
144 | BY_NAME
145 |
146 |
147 |
148 |
149 |
150 |
151 | .*:layout_width
152 | http://schemas.android.com/apk/res/android
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | .*:layout_height
162 | http://schemas.android.com/apk/res/android
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | .*:layout_.*
172 | http://schemas.android.com/apk/res/android
173 |
174 |
175 | BY_NAME
176 |
177 |
178 |
179 |
180 |
181 |
182 | .*:width
183 | http://schemas.android.com/apk/res/android
184 |
185 |
186 | BY_NAME
187 |
188 |
189 |
190 |
191 |
192 |
193 | .*:height
194 | http://schemas.android.com/apk/res/android
195 |
196 |
197 | BY_NAME
198 |
199 |
200 |
201 |
202 |
203 |
204 | .*
205 | http://schemas.android.com/apk/res/android
206 |
207 |
208 | BY_NAME
209 |
210 |
211 |
212 |
213 |
214 |
215 | .*
216 | .*
217 |
218 |
219 | BY_NAME
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/app/src/main/java/com/spjanson/restdemo/REST.java:
--------------------------------------------------------------------------------
1 | package com.spjanson.restdemo;
2 | /**
3 | * Copyright 2015 Sean Janson. All Rights Reserved.
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 | * http://www.apache.org/licenses/LICENSE-2.0
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | **/
14 |
15 | import android.app.Activity;
16 | import android.content.ContentValues;
17 | import android.os.AsyncTask;
18 |
19 | import com.google.api.client.extensions.android.http.AndroidHttp;
20 | import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
21 | import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAuthIOException;
22 | import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
23 | import com.google.api.client.googleapis.json.GoogleJsonResponseException;
24 | import com.google.api.client.http.FileContent;
25 | import com.google.api.client.http.GenericUrl;
26 | import com.google.api.client.json.gson.GsonFactory;
27 | import com.google.api.services.drive.Drive;
28 | import com.google.api.services.drive.DriveScopes;
29 | import com.google.api.services.drive.model.File;
30 | import com.google.api.services.drive.model.FileList;
31 | import com.google.api.services.drive.model.ParentReference;
32 |
33 | import java.io.IOException;
34 | import java.util.ArrayList;
35 | import java.util.Arrays;
36 | import java.util.Collections;
37 |
38 | final class REST { private REST() {}
39 | interface ConnectCBs {
40 | void onConnFail(Exception ex);
41 | void onConnOK();
42 | }
43 | private static Drive mGOOSvc;
44 | private static ConnectCBs mConnCBs;
45 | private static boolean mConnected;
46 |
47 | /************************************************************************************************
48 | * initialize Google Drive Api
49 | * @param act activity context
50 | */
51 | static boolean init(Activity act){ //UT.lg( "REST init " + email);
52 | if (act != null) try {
53 | String email = UT.AM.getEmail();
54 | if (email != null) {
55 | mConnCBs = (ConnectCBs)act;
56 | mGOOSvc = new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(),
57 | GoogleAccountCredential.usingOAuth2(UT.acx, Collections.singletonList(DriveScopes.DRIVE_FILE))
58 | .setSelectedAccountName(email)
59 | ).build();
60 | return true;
61 | }
62 | } catch (Exception e) {UT.le(e);}
63 | return false;
64 | }
65 | /**
66 | * connect
67 | */
68 | static void connect() {
69 | if (UT.AM.getEmail() != null && mGOOSvc != null) {
70 | mConnected = false;
71 | new AsyncTask() {
72 | @Override
73 | protected Exception doInBackground(Void... nadas) {
74 | try {
75 | // GoogleAuthUtil.getToken(mAct, email, DriveScopes.DRIVE_FILE); SO 30122755
76 | mGOOSvc.files().get("root").setFields("title").execute();
77 | mConnected = true;
78 | } catch (UserRecoverableAuthIOException uraIOEx) { // standard authorization failure - user fixable
79 | return uraIOEx;
80 | } catch (GoogleAuthIOException gaIOEx) { // usually PackageName /SHA1 mismatch in DevConsole
81 | return gaIOEx;
82 | } catch (IOException e) { // '404 not found' in FILE scope, consider connected
83 | if (e instanceof GoogleJsonResponseException) {
84 | if (404 == ((GoogleJsonResponseException) e).getStatusCode())
85 | mConnected = true;
86 | }
87 | } catch (Exception e) { // "the name must not be empty" indicates
88 | UT.le(e); // UNREGISTERED / EMPTY account in 'setSelectedAccountName()' above
89 | }
90 | return null;
91 | }
92 |
93 | @Override
94 | protected void onPostExecute(Exception ex) {
95 | super.onPostExecute(ex);
96 | if (mConnected) {
97 | mConnCBs.onConnOK();
98 | } else { // null indicates general error (fatal)
99 | mConnCBs.onConnFail(ex);
100 | }
101 | }
102 | }.execute();
103 | }
104 | }
105 | /**
106 | * disconnect disconnects GoogleApiClient
107 | */
108 | static void disconnect() {}
109 |
110 | /************************************************************************************************
111 | * find file/folder in GOODrive
112 | * @param prnId parent ID (optional), null searches full drive, "root" searches Drive root
113 | * @param titl file/folder name (optional)
114 | * @param mime file/folder mime type (optional)
115 | * @return arraylist of found objects
116 | */
117 | static ArrayList search(String prnId, String titl, String mime) {
118 | ArrayList gfs = new ArrayList<>();
119 | if (mGOOSvc != null && mConnected) try {
120 | // add query conditions, build query
121 | String qryClause = "'me' in owners and ";
122 | if (prnId != null) qryClause += "'" + prnId + "' in parents and ";
123 | if (titl != null) qryClause += "title = '" + titl + "' and ";
124 | if (mime != null) qryClause += "mimeType = '" + mime + "' and ";
125 | qryClause = qryClause.substring(0, qryClause.length() - " and ".length());
126 | Drive.Files.List qry = mGOOSvc.files().list().setQ(qryClause)
127 | .setFields("items(id,mimeType,labels/trashed,title),nextPageToken");
128 | String npTok = null;
129 | if (qry != null) do {
130 | FileList gLst = qry.execute();
131 | if (gLst != null) {
132 | for (File gFl : gLst.getItems()) {
133 | if (gFl.getLabels().getTrashed()) continue;
134 | gfs.add( UT.newCVs(gFl.getTitle(), gFl.getId(), gFl.getMimeType()));
135 | } //else UT.lg("failed " + gFl.getTitle());
136 | npTok = gLst.getNextPageToken();
137 | qry.setPageToken(npTok);
138 | }
139 | } while (npTok != null && npTok.length() > 0); //UT.lg("found " + vlss.size());
140 | } catch (Exception e) { UT.le(e); }
141 | return gfs;
142 | }
143 |
144 | /************************************************************************************************
145 | * create file/folder in GOODrive
146 | * @param prnId parent's ID, (null or "root") for root
147 | * @param titl file name
148 | * @return file id / null on fail
149 | */
150 | static String createFolder(String prnId, String titl) {
151 | String rsId = null;
152 | if (mGOOSvc != null && mConnected && titl != null) try {
153 | File meta = new File();
154 | meta.setParents(Collections.singletonList(new ParentReference().setId(prnId == null ? "root" : prnId)));
155 | meta.setTitle(titl);
156 | meta.setMimeType(UT.MIME_FLDR);
157 |
158 | File gFl = null;
159 | try { gFl = mGOOSvc.files().insert(meta).execute();
160 | } catch (Exception e) { UT.le(e); }
161 | if (gFl != null && gFl.getId() != null) {
162 | rsId = gFl.getId();
163 | }
164 | } catch (Exception e) { UT.le(e); }
165 | return rsId;
166 | }
167 |
168 | /************************************************************************************************
169 | * create file/folder in GOODrive
170 | * @param prnId parent's ID, (null or "root") for root
171 | * @param titl file name
172 | * @param mime file mime type
173 | * @param file file (with content) to create
174 | * @return file id / null on fail
175 | */
176 | static String createFile(String prnId, String titl, String mime, java.io.File file) {
177 | String rsId = null;
178 | if (mGOOSvc != null && mConnected && titl != null && mime != null && file != null) try {
179 | File meta = new File();
180 | meta.setParents(Collections.singletonList(new ParentReference().setId(prnId == null ? "root" : prnId)));
181 | meta.setTitle(titl);
182 | meta.setMimeType(mime);
183 |
184 | File gFl = mGOOSvc.files().insert(meta, new FileContent(mime, file)).execute();
185 | if (gFl != null)
186 | rsId = gFl.getId();
187 | } catch (Exception e) { UT.le(e); }
188 | return rsId;
189 | }
190 |
191 | /************************************************************************************************
192 | * get file contents
193 | * @param resId file driveId
194 | * @return file's content / null on fail
195 | */
196 | static byte[] read(String resId) {
197 | if (mGOOSvc != null && mConnected && resId != null) try {
198 | File gFl = mGOOSvc.files().get(resId).setFields("downloadUrl").execute();
199 | if (gFl != null){
200 | String strUrl = gFl.getDownloadUrl();
201 | return UT.is2Bytes(mGOOSvc.getRequestFactory().buildGetRequest(new GenericUrl(strUrl)).execute().getContent());
202 | }
203 | } catch (Exception e) { UT.le(e); }
204 | return null;
205 | }
206 |
207 | /************************************************************************************************
208 | * update file in GOODrive, see https://youtu.be/r2dr8_Mxr2M (WRONG?)
209 | * see https://youtu.be/r2dr8_Mxr2M .... WRONG !!!
210 | * @param resId file id
211 | * @param titl new file name (optional)
212 | * @param mime new mime type (optional, "application/vnd.google-apps.folder" indicates folder)
213 | * @param file new file content (optional)
214 | * @return file id / null on fail
215 | */
216 | static String update(String resId, String titl, String mime, String desc, java.io.File file){
217 | File gFl = null;
218 | if (mGOOSvc != null && mConnected && resId != null) try {
219 | File meta = new File();
220 | if (titl != null) meta.setTitle(titl);
221 | if (mime != null) meta.setMimeType(mime);
222 | if (desc != null) meta.setDescription(desc);
223 |
224 | if (file == null)
225 | gFl = mGOOSvc.files().patch(resId, meta).execute();
226 | else
227 | gFl = mGOOSvc.files().update(resId, meta, new FileContent(mime, file)).execute();
228 |
229 | } catch (Exception e) { UT.le(e); }
230 | return gFl == null ? null : gFl.getId();
231 | }
232 |
233 | /************************************************************************************************
234 | * trash file in GOODrive
235 | * @param resId file id
236 | * @return success status
237 | */
238 | static boolean trash(String resId) {
239 | if (mGOOSvc != null && mConnected && resId != null) try {
240 | return null != mGOOSvc.files().trash(resId).execute();
241 | } catch (Exception e) {UT.le(e);}
242 | return false;
243 | }
244 |
245 | /**
246 | * FILE / FOLDER type object inquiry
247 | * @param cv oontent values
248 | * @return TRUE if FOLDER, FALSE otherwise
249 | */
250 | static boolean isFolder(ContentValues cv) {
251 | String mime = cv.getAsString(UT.MIME);
252 | return mime != null && UT.MIME_FLDR.equalsIgnoreCase(mime);
253 | }
254 |
255 | }
256 |
257 |
--------------------------------------------------------------------------------
/app/src/main/java/com/spjanson/restdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.spjanson.restdemo;
2 | /**
3 | * Copyright 2015 Sean Janson. All Rights Reserved.
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 | * http://www.apache.org/licenses/LICENSE-2.0
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | **/
14 |
15 | import android.accounts.AccountManager;
16 | import android.content.ContentValues;
17 | import android.content.Intent;
18 | import android.os.AsyncTask;
19 | import android.os.Bundle;
20 | import android.support.v7.app.AppCompatActivity;
21 | import android.view.Menu;
22 | import android.view.MenuItem;
23 | import android.widget.TextView;
24 | import android.widget.Toast;
25 |
26 | import com.google.android.gms.auth.GoogleAuthUtil;
27 | import com.google.android.gms.common.AccountPicker;
28 | import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAuthIOException;
29 | import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
30 |
31 | import java.io.File;
32 | import java.util.ArrayList;
33 |
34 | public class MainActivity extends AppCompatActivity implements REST.ConnectCBs{
35 | private static final int REQ_ACCPICK = 1;
36 | private static final int REQ_CONNECT = 2;
37 |
38 | private static TextView mDispTxt;
39 | private static boolean mBusy;
40 |
41 | @Override
42 | protected void onCreate(Bundle bundle) { super.onCreate(bundle);
43 | setContentView(R.layout.activity_main);
44 | mDispTxt = (TextView)findViewById(R.id.tvDispText);
45 | if (bundle == null) {
46 | UT.init(this);
47 | if (!REST.init(this)) {
48 | startActivityForResult(AccountPicker.newChooseAccountIntent(null,
49 | null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null),
50 | REQ_ACCPICK);
51 | }
52 | }
53 | }
54 |
55 | @Override
56 | protected void onResume() { super.onResume();
57 | REST.connect();
58 | }
59 | @Override
60 | protected void onPause() { super.onPause();
61 | REST.disconnect();
62 | }
63 |
64 | @Override
65 | public boolean onCreateOptionsMenu(Menu menu) {
66 | getMenuInflater().inflate(R.menu.menu_main, menu);
67 | return true;
68 | }
69 | @Override
70 | public boolean onOptionsItemSelected(MenuItem item) {
71 | switch (item.getItemId()) {
72 | case R.id.action_create: {
73 | createTree(UT.time2Titl(null));
74 | return true;
75 | }
76 | case R.id.action_list: {
77 | testTree();
78 | return true;
79 | }
80 | case R.id.action_delete: {
81 | deleteTree();
82 | return true;
83 | }
84 | case R.id.action_account: {
85 | mDispTxt.setText("");
86 | startActivityForResult(AccountPicker.newChooseAccountIntent(
87 | null, null, new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE}, true, null, null, null, null), REQ_ACCPICK);
88 | return true;
89 | }
90 | }
91 | return super.onOptionsItemSelected(item);
92 | }
93 |
94 | @Override
95 | protected void onActivityResult(int request, int result, Intent data) {
96 | switch (request) {
97 | case REQ_CONNECT:
98 | if (result == RESULT_OK)
99 | REST.connect();
100 | else { UT.lg("act result - NO AUTH");
101 | suicide(R.string.err_auth_nogo); //---------------------------------->>>
102 | }
103 | break;
104 | case REQ_ACCPICK:
105 | if (data != null && data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME) != null)
106 | UT.AM.setEmail(data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME));
107 | if (!REST.init(this)) { UT.lg("act result - NO ACCOUNT");
108 | suicide(R.string.err_auth_accpick); //---------------------------------->>>
109 | }
110 | break;
111 | }
112 | super.onActivityResult(request, result, data);
113 | }
114 |
115 | // *** connection callbacks ***********************************************************
116 | @Override
117 | public void onConnOK() {
118 | mDispTxt.append("\n\nCONNECTED TO: " + UT.AM.getEmail());
119 | }
120 |
121 | @Override
122 | public void onConnFail(Exception ex) {
123 | if (ex == null) { UT.lg("connFail - UNSPECD 1");
124 | suicide(R.string.err_auth_dono); return; //---------------------------------->>>
125 | }
126 | if (ex instanceof UserRecoverableAuthIOException) { UT.lg("connFail - has res");
127 | startActivityForResult((((UserRecoverableAuthIOException) ex).getIntent()), REQ_CONNECT);
128 | } else if (ex instanceof GoogleAuthIOException) { UT.lg("connFail - SHA1?");
129 | if (ex.getMessage() != null) suicide(ex.getMessage()); //--------------------->>>
130 | else suicide(R.string.err_auth_sha); //---------------------------------->>>
131 | } else { UT.lg("connFail - UNSPECD 2");
132 | suicide(R.string.err_auth_dono); //---------------------------------->>>
133 | }
134 | }
135 |
136 | /**
137 | * creates a directory tree to house a text file
138 | * @param titl file name (confirms to 'yyMMdd-HHmmss' and it's name is used
139 | * to create it's parent folder 'yyyy-MM' under a common root 'GDRTDemo'
140 | * GDRTDemo ---+--- yyyy-MM ---+--- yyMMdd-HHmmss
141 | * | +--- yyMMdd-HHmmss
142 | * +--- yyyy-MM ---+--- yyMMdd-HHmmss
143 | * +--- yyMMdd-HHmmss
144 | * ....
145 | */
146 | private void createTree(final String titl) {
147 | if (titl != null && !mBusy) {
148 | mDispTxt.setText("UPLOADING\n");
149 |
150 | new AsyncTask() {
151 | private String findOrCreateFolder(String prnt, String titl){
152 | ArrayList cvs = REST.search(prnt, titl, UT.MIME_FLDR);
153 | String id, txt;
154 | if (cvs.size() > 0) {
155 | txt = "found ";
156 | id = cvs.get(0).getAsString(UT.GDID);
157 | } else {
158 | id = REST.createFolder(prnt, titl);
159 | txt = "created ";
160 | }
161 | if (id != null)
162 | txt += titl;
163 | else
164 | txt = "failed " + titl;
165 | publishProgress(txt);
166 | return id;
167 | }
168 |
169 | @Override
170 | protected Void doInBackground(Void... params) {
171 | mBusy = true;
172 | String rsid = findOrCreateFolder("root", UT.MYROOT);
173 | if (rsid != null) {
174 | rsid = findOrCreateFolder(rsid, UT.titl2Month(titl));
175 | if (rsid != null) {
176 | File fl = UT.str2File("content of " + titl, "tmp" );
177 | String id = null;
178 | if (fl != null) {
179 | id = REST.createFile(rsid, titl, UT.MIME_TEXT, fl);
180 | fl.delete();
181 | }
182 | if (id != null)
183 | publishProgress("created " + titl);
184 | else
185 | publishProgress("failed " + titl);
186 | }
187 | }
188 | return null;
189 | }
190 | @Override
191 | protected void onProgressUpdate(String... strings) { super.onProgressUpdate(strings);
192 | mDispTxt.append("\n" + strings[0]);
193 | }
194 | @Override
195 | protected void onPostExecute(Void nada) { super.onPostExecute(nada);
196 | mDispTxt.append("\n\nDONE");
197 | mBusy = false;
198 | }
199 | }.execute();
200 | }
201 | }
202 |
203 | /**
204 | * scans folder tree created by this app listing folders / files, updating file's
205 | * 'description' meadata in the process
206 | */
207 | private void testTree() {
208 | if (!mBusy) {
209 | mDispTxt.setText("DOWNLOADING\n");
210 | new AsyncTask() {
211 |
212 | private void iterate(ContentValues gfParent) {
213 | ArrayList cvs = REST.search(gfParent.getAsString(UT.GDID), null, null);
214 | if (cvs != null) for (ContentValues cv : cvs) {
215 | String gdid = cv.getAsString(UT.GDID);
216 | String titl = cv.getAsString(UT.TITL);
217 |
218 | if (REST.isFolder(cv)) {
219 | publishProgress(titl);
220 | iterate(cv);
221 | } else {
222 | byte[] buf = REST.read(gdid);
223 | if (buf == null)
224 | titl += " failed";
225 | publishProgress(titl);
226 | String str = buf == null ? "" : new String(buf);
227 | File fl = UT.str2File(str + "\n updated " + UT.time2Titl(null), "tmp" );
228 | if (fl != null) {
229 | String desc = "seen " + UT.time2Titl(null);
230 | REST.update(gdid, null, null, desc, fl);
231 | fl.delete();
232 | }
233 | }
234 | }
235 | }
236 |
237 | @Override
238 | protected Void doInBackground(Void... params) {
239 | mBusy = true;
240 | ArrayList gfMyRoot = REST.search("root", UT.MYROOT, null);
241 | if (gfMyRoot != null && gfMyRoot.size() == 1 ){
242 | publishProgress(gfMyRoot.get(0).getAsString(UT.TITL));
243 | iterate(gfMyRoot.get(0));
244 | }
245 | return null;
246 | }
247 |
248 | @Override
249 | protected void onProgressUpdate(String... strings) {
250 | super.onProgressUpdate(strings);
251 | mDispTxt.append("\n" + strings[0]);
252 | }
253 |
254 | @Override
255 | protected void onPostExecute(Void nada) {
256 | super.onPostExecute(nada);
257 | mDispTxt.append("\n\nDONE");
258 | mBusy = false;
259 | }
260 | }.execute();
261 | }
262 | }
263 |
264 | /**
265 | * scans folder tree created by this app deleting folders / files in the process
266 | */
267 | private void deleteTree() {
268 | if (!mBusy) {
269 | mDispTxt.setText("DELETING\n");
270 | new AsyncTask() {
271 |
272 | private void iterate(ContentValues gfParent) {
273 | ArrayList cvs = REST.search(gfParent.getAsString(UT.GDID), null, null);
274 | if (cvs != null) for (ContentValues cv : cvs) {
275 | String titl = cv.getAsString(UT.TITL);
276 | String gdid = cv.getAsString(UT.GDID);
277 | if (REST.isFolder(cv))
278 | iterate(cv);
279 | publishProgress(" " + titl + (REST.trash(gdid) ? " OK" : " FAIL"));
280 | }
281 | }
282 |
283 | @Override
284 | protected Void doInBackground(Void... params) {
285 | mBusy = true;
286 | ArrayList gfMyRoot = REST.search("root", UT.MYROOT, null);
287 | if (gfMyRoot != null && gfMyRoot.size() == 1 ){
288 | ContentValues cv = gfMyRoot.get(0);
289 | iterate(cv);
290 | String titl = cv.getAsString(UT.TITL);
291 | String gdid = cv.getAsString(UT.GDID);
292 | publishProgress(" " + titl + (REST.trash(gdid) ? " OK" : " FAIL"));
293 | }
294 | return null;
295 | }
296 |
297 | @Override
298 | protected void onProgressUpdate(String... strings) {
299 | super.onProgressUpdate(strings);
300 | mDispTxt.append("\n" + strings[0]);
301 | }
302 |
303 | @Override
304 | protected void onPostExecute(Void nada) {
305 | super.onPostExecute(nada);
306 | mDispTxt.append("\n\nDONE");
307 | mBusy = false;
308 | }
309 | }.execute();
310 | }
311 | }
312 |
313 | private void suicide(int rid) {
314 | UT.AM.setEmail(null);
315 | Toast.makeText(this, rid, Toast.LENGTH_LONG).show();
316 | finish();
317 | }
318 | private void suicide(String msg) {
319 | UT.AM.setEmail(null);
320 | Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
321 | finish();
322 | }
323 | }
324 |
--------------------------------------------------------------------------------