diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml index 524d714..ee81eae 100644 --- a/.github/workflows/gradle-build.yml +++ b/.github/workflows/gradle-build.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - java: [11, 17] + java: [17] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 343c8f2..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -script: - # By default Travis CI executes './gradlew build connectedCheck' if no 'script:' section found. - - ./gradlew build - -language: android - -jdk: - - openjdk11 - -android: - components: - - tools - - build-tools-29.0.3 - - android-29 - - extra-android-m2repository - -notifications: - email: false - slack: elimu-ai:5hNcmHPFkAETjJZjrkBlNTxr diff --git a/app/build.gradle b/app/build.gradle index 27d93b9..e2f6d23 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,12 +2,13 @@ apply plugin: 'com.android.application' apply plugin: 'org.ajoberstar.grgit' android { - compileSdk 33 + namespace 'ai.elimu.content_provider' + compileSdk 34 defaultConfig { applicationId "ai.elimu.content_provider" minSdkVersion 24 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 1002021 versionName "1.2.21-SNAPSHOT" setProperty("archivesBaseName", "${applicationId}-${versionCode}") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 342bce8..6fb96a7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + @@ -33,6 +32,11 @@ android:authorities="${applicationId}.provider.letter_provider" android:enabled="true" android:exported="true" /> + pathSegments = uri.getPathSegments(); + Log.i(getClass().getName(), "pathSegments: " + pathSegments); + String idAsString = pathSegments.get(1); + Long id = Long.valueOf(idAsString); + Log.i(getClass().getName(), "id: " + id); + + final Cursor cursor; + + // Get the Room Cursor + cursor = letterSoundDao.load_Cursor(id); + Log.i(getClass().getName(), "cursor: " + cursor); + + cursor.setNotificationUri(context.getContentResolver(), uri); + + return cursor; + } else { + throw new IllegalArgumentException("Unknown URI: " + uri); + } + } + + @Override + public String getType(Uri uri) { + Log.i(getClass().getName(), "getType"); + + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + Log.i(getClass().getName(), "insert"); + + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + Log.i(getClass().getName(), "update"); + + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + Log.i(getClass().getName(), "delete"); + + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java b/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java index b37c1d0..ae9afa3 100644 --- a/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java +++ b/app/src/main/java/ai/elimu/content_provider/room/dao/LetterSoundDao.java @@ -1,5 +1,7 @@ package ai.elimu.content_provider.room.dao; +import android.database.Cursor; + import androidx.room.Dao; import androidx.room.Insert; import androidx.room.Query; @@ -14,9 +16,15 @@ public interface LetterSoundDao { @Insert void insert(LetterSound letterSound); + @Query("SELECT * FROM LetterSound WHERE id = :id") + Cursor load_Cursor(Long id); + @Query("SELECT * FROM LetterSound") List loadAll(); + @Query("SELECT * FROM LetterSound") + Cursor loadAll_Cursor(); + @Query("DELETE FROM LetterSound") void deleteAll(); } diff --git a/build.gradle b/build.gradle index 19fb700..c26ebdb 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.3' + classpath 'com.android.tools.build:gradle:8.1.4' classpath 'org.ajoberstar.grgit:grgit-gradle:5.0.0' // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index 199d16e..46309a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,7 @@ org.gradle.jvmargs=-Xmx1536m android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..ccebba7 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b1159fc..309b4e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index c53aefa..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -205,6 +209,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/utils/build.gradle b/utils/build.gradle index a592633..bd1dd9b 100644 --- a/utils/build.gradle +++ b/utils/build.gradle @@ -1,14 +1,14 @@ plugins { id 'com.android.library' - id 'maven-publish' } android { - compileSdk 33 + namespace 'ai.elimu.content_provider.utils' + compileSdk 34 defaultConfig { minSdkVersion 24 - targetSdkVersion 33 + targetSdkVersion 34 versionCode 1002021 versionName "1.2.21-SNAPSHOT" setProperty("archivesBaseName", "utils-${versionName}") @@ -29,22 +29,3 @@ dependencies { implementation 'com.github.elimu-ai:model:model-2.0.66' // See https://jitpack.io/#elimu-ai/model implementation 'com.github.elimu-ai:analytics:3.1.11@aar' // See https://jitpack.io/#elimu-ai/analytics } - -// See https://docs.gradle.org/current/dsl/org.gradle.api.publish.maven.MavenPublication.html -// Usage: ./gradlew clean build publish -PmavenUsername=***** -PmavenPassword=***** -publishing { - publications { - utils(MavenPublication) { - groupId 'ai.elimu.content_provider' - artifactId 'utils' - version '1.2.21-SNAPSHOT' - artifact("${buildDir}/outputs/aar/utils-${version}-release.aar") - } - } - repositories { - maven { - credentials(PasswordCredentials) - url "https://maven.pkg.github.com/elimu-ai/content-provider" - } - } -} diff --git a/utils/src/main/AndroidManifest.xml b/utils/src/main/AndroidManifest.xml index b362a53..a5918e6 100644 --- a/utils/src/main/AndroidManifest.xml +++ b/utils/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + \ No newline at end of file diff --git a/utils/src/main/java/ai/elimu/content_provider/utils/ContentProviderUtil.java b/utils/src/main/java/ai/elimu/content_provider/utils/ContentProviderUtil.java index 6f49dfc..0ec020d 100644 --- a/utils/src/main/java/ai/elimu/content_provider/utils/ContentProviderUtil.java +++ b/utils/src/main/java/ai/elimu/content_provider/utils/ContentProviderUtil.java @@ -15,6 +15,7 @@ import ai.elimu.content_provider.utils.converter.CursorToEmojiGsonConverter; import ai.elimu.content_provider.utils.converter.CursorToImageGsonConverter; import ai.elimu.content_provider.utils.converter.CursorToLetterGsonConverter; +import ai.elimu.content_provider.utils.converter.CursorToLetterSoundGsonConverter; import ai.elimu.content_provider.utils.converter.CursorToStoryBookChapterGsonConverter; import ai.elimu.content_provider.utils.converter.CursorToStoryBookGsonConverter; import ai.elimu.content_provider.utils.converter.CursorToWordGsonConverter; @@ -24,6 +25,7 @@ import ai.elimu.model.v2.gson.content.EmojiGson; import ai.elimu.model.v2.gson.content.ImageGson; import ai.elimu.model.v2.gson.content.LetterGson; +import ai.elimu.model.v2.gson.content.LetterSoundGson; import ai.elimu.model.v2.gson.content.StoryBookChapterGson; import ai.elimu.model.v2.gson.content.StoryBookGson; import ai.elimu.model.v2.gson.content.StoryBookParagraphGson; @@ -100,6 +102,45 @@ public static List getAllLetterGsons(Context context, String content return letterGsons; } + /** + * This method is only meant to be used for testing purposes during development. + */ + public static List getAllLetterSoundGsons(Context context, String contentProviderApplicationId) { + Log.i(ContentProviderUtil.class.getName(), "getAllLetterSoundGsons"); + + List letterSoundGsons = new ArrayList<>(); + + Uri uri = Uri.parse("content://" + contentProviderApplicationId + ".provider.letter_sound_provider/letter_sounds"); + Log.i(ContentProviderUtil.class.getName(), "uri: " + uri); + Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); + Log.i(ContentProviderUtil.class.getName(), "cursor: " + cursor); + if (cursor == null) { + Log.e(ContentProviderUtil.class.getName(), "cursor == null"); + Toast.makeText(context, "cursor == null", Toast.LENGTH_LONG).show(); + } else { + Log.i(ContentProviderUtil.class.getName(), "cursor.getCount(): " + cursor.getCount()); + if (cursor.getCount() == 0) { + Log.e(ContentProviderUtil.class.getName(), "cursor.getCount() == 0"); + } else { + boolean isLast = false; + while (!isLast) { + cursor.moveToNext(); + + // Convert from Room to Gson + LetterSoundGson letterSoundGson = CursorToLetterSoundGsonConverter.getLetterSoundGson(cursor); + + letterSoundGsons.add(letterSoundGson); + + isLast = cursor.isLast(); + } + cursor.close(); + Log.i(ContentProviderUtil.class.getName(), "cursor.isClosed(): " + cursor.isClosed()); + } + } + + return letterSoundGsons; + } + /** * Returns a list of words currently available to the student. *

diff --git a/utils/src/main/java/ai/elimu/content_provider/utils/converter/CursorToLetterSoundGsonConverter.java b/utils/src/main/java/ai/elimu/content_provider/utils/converter/CursorToLetterSoundGsonConverter.java new file mode 100644 index 0000000..8f76795 --- /dev/null +++ b/utils/src/main/java/ai/elimu/content_provider/utils/converter/CursorToLetterSoundGsonConverter.java @@ -0,0 +1,33 @@ +package ai.elimu.content_provider.utils.converter; + +import android.database.Cursor; +import android.util.Log; + +import java.util.Arrays; + +import ai.elimu.model.v2.gson.content.LetterSoundGson; + +public class CursorToLetterSoundGsonConverter { + + public static LetterSoundGson getLetterSoundGson(Cursor cursor) { + Log.i(CursorToLetterSoundGsonConverter.class.getName(), "getLetterSoundGson"); + + Log.i(CursorToLetterSoundGsonConverter.class.getName(), "Arrays.toString(cursor.getColumnNames()): " + Arrays.toString(cursor.getColumnNames())); + + int columnIndexId = cursor.getColumnIndex("id"); + Long id = cursor.getLong(columnIndexId); + Log.i(CursorToLetterSoundGsonConverter.class.getName(), "id: " + id); + + int columnIndexRevisionNumber = cursor.getColumnIndex("revisionNumber"); + Integer revisionNumber = cursor.getInt(columnIndexRevisionNumber); + Log.i(CursorToLetterSoundGsonConverter.class.getName(), "revisionNumber: " + revisionNumber); + + LetterSoundGson letterSound = new LetterSoundGson(); + letterSound.setId(id); + letterSound.setRevisionNumber(revisionNumber); + // TODO: letterSound.setLetters(letters); + // TODO: letterSound.setSounds(sounds); + + return letterSound; + } +}