├── .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 | 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 | 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 | 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 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 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 | 8 | 9 | 10 | 11 | 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 | 227 | 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 | --------------------------------------------------------------------------------