From b3dadd1d31946402b30dfa94e02285738178d31f Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 15 Oct 2018 01:32:16 -0500 Subject: [PATCH 1/2] Move to java 1.8 to allow for lambda expressions --- app/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 2721d65e..4f25b8e6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,10 @@ android { signingConfig signingConfigs.release } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { From a9268a23400d4442914a182a878cc71d1fde40a6 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Tue, 16 Oct 2018 14:23:05 -0500 Subject: [PATCH 2/2] Demonstrate StatsProvider API usage Uses new read-only permission, goes off an options menu click --- app/src/main/AndroidManifest.xml | 10 ++- .../com/ichi2/apisample/AnkiDroidHelper.java | 28 +++++++- .../com/ichi2/apisample/MainActivity.java | 7 +- .../com/ichi2/apisample/StatsActivity.java | 71 +++++++++++++++++++ app/src/main/res/layout/activity_stats.xml | 30 ++++++++ app/src/main/res/menu/main_menu.xml | 6 +- app/src/main/res/values/strings.xml | 6 ++ 7 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/ichi2/apisample/StatsActivity.java create mode 100644 app/src/main/res/layout/activity_stats.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 95d940d3..b8fa0c1e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,13 +1,17 @@ + + + android:theme="@style/Theme.AppCompat" + tools:ignore="GoogleAppIndexingWarning"> @@ -17,6 +21,10 @@ + + diff --git a/app/src/main/java/com/ichi2/apisample/AnkiDroidHelper.java b/app/src/main/java/com/ichi2/apisample/AnkiDroidHelper.java index 0c6ed91f..e0edb23e 100644 --- a/app/src/main/java/com/ichi2/apisample/AnkiDroidHelper.java +++ b/app/src/main/java/com/ichi2/apisample/AnkiDroidHelper.java @@ -25,6 +25,10 @@ public class AnkiDroidHelper { private static final String DECK_REF_DB = "com.ichi2.anki.api.decks"; private static final String MODEL_REF_DB = "com.ichi2.anki.api.models"; + // Temporary until new API is published and we can import static as with READ_WRITE_PERMISSION + public static final String READ_PERMISSION = "com.ichi2.anki.permission.READ_DATABASE"; + + private AddContentApi mApi; private Context mContext; @@ -46,22 +50,42 @@ public static boolean isApiAvailable(Context context) { return AddContentApi.getAnkiDroidPackageName(context) != null; } + /** + * Whether or not we should request read-only access to the AnkiDroid API + */ + public boolean shouldRequestReadPermission() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + return false; + } + return shouldRequestReadWritePermission() + || ContextCompat.checkSelfPermission(mContext, READ_PERMISSION) != PackageManager.PERMISSION_GRANTED; + } + /** * Whether or not we should request full access to the AnkiDroid API */ - public boolean shouldRequestPermission() { + public boolean shouldRequestReadWritePermission() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return false; } return ContextCompat.checkSelfPermission(mContext, READ_WRITE_PERMISSION) != PackageManager.PERMISSION_GRANTED; } + /** + * Request permission from the user for read-only access to the AnkiDroid API (for SDK 23+) + * @param callbackActivity An Activity which implements onRequestPermissionsResult() + * @param callbackCode The callback code to be used in onRequestPermissionsResult() + */ + public void requestReadPermission(Activity callbackActivity, int callbackCode) { + ActivityCompat.requestPermissions(callbackActivity, new String[]{READ_PERMISSION}, callbackCode); + } + /** * Request permission from the user to access the AnkiDroid API (for SDK 23+) * @param callbackActivity An Activity which implements onRequestPermissionsResult() * @param callbackCode The callback code to be used in onRequestPermissionsResult() */ - public void requestPermission(Activity callbackActivity, int callbackCode) { + public void requestReadWritePermission(Activity callbackActivity, int callbackCode) { ActivityCompat.requestPermissions(callbackActivity, new String[]{READ_WRITE_PERMISSION}, callbackCode); } diff --git a/app/src/main/java/com/ichi2/apisample/MainActivity.java b/app/src/main/java/com/ichi2/apisample/MainActivity.java index 993cec0d..a0cc91a1 100644 --- a/app/src/main/java/com/ichi2/apisample/MainActivity.java +++ b/app/src/main/java/com/ichi2/apisample/MainActivity.java @@ -80,6 +80,9 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.stats_menu_item: + startActivity(new Intent(this, StatsActivity.class)); + return true; default: return super.onOptionsItemSelected(item); } @@ -216,8 +219,8 @@ public boolean onMenuItemClick(MenuItem item) { // Handle when the submenu items are clicked if (item.getItemId() == ANKIDROID_INSTANT_ADD) { // Request permission to access API if required - if (mAnkiDroid.shouldRequestPermission()) { - mAnkiDroid.requestPermission(MainActivity.this, AD_PERM_REQUEST); + if (mAnkiDroid.shouldRequestReadWritePermission()) { + mAnkiDroid.requestReadWritePermission(MainActivity.this, AD_PERM_REQUEST); return true; } // Add all data using AnkiDroid provider diff --git a/app/src/main/java/com/ichi2/apisample/StatsActivity.java b/app/src/main/java/com/ichi2/apisample/StatsActivity.java new file mode 100644 index 00000000..b6ae1e50 --- /dev/null +++ b/app/src/main/java/com/ichi2/apisample/StatsActivity.java @@ -0,0 +1,71 @@ +package com.ichi2.apisample; + +import android.content.ContentResolver; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; + +public class StatsActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { + + private static final int AD_PERM_REQUEST = 0; + private AnkiDroidHelper mAnkiDroid; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mAnkiDroid = new AnkiDroidHelper(this); + + setContentView(R.layout.activity_stats); + if (!AnkiDroidHelper.isApiAvailable(this)) { + Toast.makeText(this, R.string.api_not_available, Toast.LENGTH_LONG).show(); + finishActivity(-1); + return; + } + + if (mAnkiDroid.shouldRequestReadPermission()) { + mAnkiDroid.requestReadPermission(this, AD_PERM_REQUEST); + } else { + displayCardCount(); + } + } + + private void displayCardCount() { + TextView matureText = findViewById(R.id.count_mature); + TextView youngText = findViewById(R.id.count_young); + TextView newCount = findViewById(R.id.count_new); + TextView suspendedCount = findViewById(R.id.count_suspended); + + Cursor countCursor = fetchCardCount(); + + matureText.setText(getString(R.string.mature_cards, countCursor.getInt(0))); + youngText.setText(getString(R.string.young_cards, countCursor.getInt(1))); + newCount.setText(getString(R.string.new_cards, countCursor.getInt(2))); + suspendedCount.setText(getString(R.string.suspended_cards, countCursor.getInt(3))); + } + + private Cursor fetchCardCount() { + ContentResolver resolver = getApplicationContext().getContentResolver(); + Cursor countCursor = resolver.query(Uri.parse("content://com.ichi2.anki.stats/cardcount"), null, null, null, null); + countCursor.moveToFirst(); + return countCursor; + } + + + public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if ((requestCode == AD_PERM_REQUEST) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) { + displayCardCount(); + } else { + Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_LONG).show(); + finishActivity(-1); + } + } +} diff --git a/app/src/main/res/layout/activity_stats.xml b/app/src/main/res/layout/activity_stats.xml new file mode 100644 index 00000000..2fd3132b --- /dev/null +++ b/app/src/main/res/layout/activity_stats.xml @@ -0,0 +1,30 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml index 85ea3152..51545c42 100644 --- a/app/src/main/res/menu/main_menu.xml +++ b/app/src/main/res/menu/main_menu.xml @@ -1,8 +1,8 @@ - + android:visible="true" + android:title="@string/card_counts"/> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 37c8bf92..d0aa74e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,5 +7,11 @@ %d items selected %d items added to AnkiDroid Error adding cards to AnkiDroid + AnkiDroid API not available Couldn\'t get permission to access the AnkiDroid database + Card Counts + Mature cards %d + Young cards %d + New cards %d + Suspended cards %d