#831 Migrate from SQLiteOpenHelper to Room

Fix some build bugs
This commit is contained in:
Stefan Niedermann 2020-10-05 16:13:19 +02:00
parent b8048cb11b
commit e58623a078
7 changed files with 95 additions and 78 deletions

View file

@ -357,7 +357,7 @@ public abstract class BaseNoteFragment extends BrandedFragment implements Catego
@Override
public void onCategoryChosen(String category) {
sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, null);
roomDatabase.setCategory(ssoAccount, note, category, null);
listener.onNoteUpdated(note);
}

View file

@ -1001,7 +1001,7 @@ public class MainActivity extends LockedActivity implements NoteClickListener, V
for (Integer i : new ArrayList<>(adapter.getSelected())) {
DBNote note = (DBNote) adapter.getItem(i);
note.setCategory(category);
sqliteOpenHelperDatabase.setCategory(ssoAccount, note, category, this::refreshLists);
roomDatabase.setCategory(ssoAccount, note, category, this::refreshLists);
}
mActionMode.finish();

View file

@ -36,6 +36,7 @@ import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.branding.BrandedSnackbar;
import it.niedermann.owncloud.notes.exception.ExceptionDialogFragment;
import it.niedermann.owncloud.notes.persistence.entity.LocalAccountEntity;
import it.niedermann.owncloud.notes.persistence.entity.NoteEntity;
import it.niedermann.owncloud.notes.shared.model.CloudNote;
import it.niedermann.owncloud.notes.shared.model.DBNote;
import it.niedermann.owncloud.notes.shared.model.DBStatus;
@ -362,8 +363,9 @@ public class NoteServerSyncHelper {
Log.d(TAG, "pushLocalChanges()");
boolean success = true;
List<DBNote> notes = sqliteOpenHelperDatabase.getLocalModifiedNotes(localAccount.getId());
for (DBNote note : notes) {
List<NoteEntity> notes = roomDatabase.getNoteDao().getLocalModifiedNotes(localAccount.getId());
for (NoteEntity noteEntity : notes) {
DBNote note = NoteEntity.entityToDBNote(noteEntity);
Log.d(TAG, " Process Local Note: " + note);
try {
CloudNote remoteNote;
@ -518,7 +520,7 @@ public class NoteServerSyncHelper {
}
}
sqliteOpenHelperDatabase.notifyWidgets();
sqliteOpenHelperDatabase.updateDynamicShortcuts(localAccount.getId());
roomDatabase.updateDynamicShortcuts(localAccount.getId());
// start next sync if scheduled meanwhile
if (syncScheduled.containsKey(ssoAccount.name) && syncScheduled.get(ssoAccount.name) != null && Boolean.TRUE.equals(syncScheduled.get(ssoAccount.name))) {
scheduleSync(ssoAccount, false);

View file

@ -262,19 +262,6 @@ public class NotesDatabase extends AbstractNotesDatabase {
return getNotesCustom(accountId, TextUtils.join(" AND ", where), args.toArray(new String[]{}), order, true);
}
/**
* Returns a list of all Notes in the Database which were modified locally
*
* @return {@link List<DBNote>}
*/
@NonNull
@WorkerThread
List<DBNote> getLocalModifiedNotes(long accountId) {
validateAccountId(accountId);
return getNotesCustom(accountId, key_status + " != ? AND " + key_account_id + " = ?", new String[]{DBStatus.VOID.getTitle(), "" + accountId}, null, false);
}
/**
* This method return all of the categories with given accountId
*
@ -363,32 +350,6 @@ public class NotesDatabase extends AbstractNotesDatabase {
serverSyncHelper.scheduleSync(ssoAccount, true);
}
/**
* Set the category for a given note.
* This method will search in the database to find out the category id in the db.
* If there is no such category existing, this method will create it and search again.
*
* @param ssoAccount The single sign on account
* @param note The note which will be updated
* @param category The category title which should be used to find the category id.
* @param callback When the synchronization is finished, this callback will be invoked (optional).
*/
public void setCategory(SingleSignOnAccount ssoAccount, @NonNull DBNote note, @NonNull String category, @Nullable ISyncCallback callback) {
note.setCategory(category);
note.setStatus(DBStatus.LOCAL_EDITED);
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues(2);
values.put(key_status, note.getStatus().getTitle());
int id = getCategoryIdByTitle(note.getAccountId(), note.getCategory());
values.put(key_category, id);
db.update(table_notes, values, key_id + " = ?", new String[]{String.valueOf(note.getId())});
removeEmptyCategory(note.getAccountId());
if (callback != null) {
serverSyncHelper.addCallbackPush(ssoAccount, callback);
}
serverSyncHelper.scheduleSync(ssoAccount, true);
}
private long addCategory(long accountId, @NonNull String title) {
validateAccountId(accountId);
SQLiteDatabase db = getWritableDatabase();
@ -512,40 +473,6 @@ public class NotesDatabase extends AbstractNotesDatabase {
updateNoteListWidgets(getContext());
}
void updateDynamicShortcuts(long accountId) {
new Thread(() -> {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
ShortcutManager shortcutManager = getContext().getApplicationContext().getSystemService(ShortcutManager.class);
if (shortcutManager != null) {
if (!shortcutManager.isRateLimitingActive()) {
List<ShortcutInfo> newShortcuts = new ArrayList<>();
for (DBNote note : getRecentNotes(accountId)) {
if (!TextUtils.isEmpty(note.getTitle())) {
Intent intent = new Intent(getContext().getApplicationContext(), EditNoteActivity.class);
intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId());
intent.setAction(ACTION_SHORTCUT);
newShortcuts.add(new ShortcutInfo.Builder(getContext().getApplicationContext(), note.getId() + "")
.setShortLabel(note.getTitle() + "")
.setIcon(Icon.createWithResource(getContext().getApplicationContext(), note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp))
.setIntent(intent)
.build());
} else {
// Prevent crash https://github.com/stefan-niedermann/nextcloud-notes/issues/613
Log.e(TAG, "shortLabel cannot be empty " + note);
}
}
Log.d(TAG, "Update dynamic shortcuts");
shortcutManager.removeAllDynamicShortcuts();
shortcutManager.addDynamicShortcuts(newShortcuts);
}
}
}
}).start();
}
/**
* @param apiVersion has to be a JSON array as a string <code>["0.2", "1.0", ...]</code>
* @return whether or not the given {@link ApiVersion} has been written to the database

View file

@ -1,11 +1,18 @@
package it.niedermann.owncloud.notes.persistence;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.room.Database;
import androidx.room.Room;
@ -16,9 +23,12 @@ import androidx.sqlite.db.SupportSQLiteDatabase;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.edit.EditNoteActivity;
import it.niedermann.owncloud.notes.persistence.dao.CategoryDao;
import it.niedermann.owncloud.notes.persistence.dao.LocalAccountDao;
import it.niedermann.owncloud.notes.persistence.dao.NoteDao;
@ -30,8 +40,10 @@ import it.niedermann.owncloud.notes.shared.model.Capabilities;
import it.niedermann.owncloud.notes.shared.model.CloudNote;
import it.niedermann.owncloud.notes.shared.model.DBNote;
import it.niedermann.owncloud.notes.shared.model.DBStatus;
import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
import it.niedermann.owncloud.notes.shared.util.ColorUtil;
import static it.niedermann.owncloud.notes.edit.EditNoteActivity.ACTION_SHORTCUT;
import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt;
import static it.niedermann.owncloud.notes.widget.notelist.NoteListWidget.updateNoteListWidgets;
import static it.niedermann.owncloud.notes.widget.singlenote.SingleNoteWidget.updateSingleNoteWidgets;
@ -251,4 +263,60 @@ public abstract class NotesRoomDatabase extends RoomDatabase {
updateSingleNoteWidgets(context);
updateNoteListWidgets(context);
}
void updateDynamicShortcuts(long accountId) {
new Thread(() -> {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
ShortcutManager shortcutManager = context.getApplicationContext().getSystemService(ShortcutManager.class);
if (shortcutManager != null) {
if (!shortcutManager.isRateLimitingActive()) {
List<ShortcutInfo> newShortcuts = new ArrayList<>();
for (NoteEntity note : getNoteDao().getRecentNotes(accountId)) {
if (!TextUtils.isEmpty(note.getTitle())) {
Intent intent = new Intent(context.getApplicationContext(), EditNoteActivity.class);
intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId());
intent.setAction(ACTION_SHORTCUT);
newShortcuts.add(new ShortcutInfo.Builder(context.getApplicationContext(), note.getId() + "")
.setShortLabel(note.getTitle() + "")
.setIcon(Icon.createWithResource(context.getApplicationContext(), note.getFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp))
.setIntent(intent)
.build());
} else {
// Prevent crash https://github.com/stefan-niedermann/nextcloud-notes/issues/613
Log.e(TAG, "shortLabel cannot be empty " + note);
}
}
Log.d(TAG, "Update dynamic shortcuts");
shortcutManager.removeAllDynamicShortcuts();
shortcutManager.addDynamicShortcuts(newShortcuts);
}
}
}
}).start();
}
/**
* Set the category for a given note.
* This method will search in the database to find out the category id in the db.
* If there is no such category existing, this method will create it and search again.
*
* @param ssoAccount The single sign on account
* @param note The note which will be updated
* @param category The category title which should be used to find the category id.
* @param callback When the synchronization is finished, this callback will be invoked (optional).
*/
public void setCategory(SingleSignOnAccount ssoAccount, @NonNull DBNote note, @NonNull String category, @Nullable ISyncCallback callback) {
note.setCategory(category);
getNoteDao().updateStatus(note.getId(), DBStatus.LOCAL_DELETED);
long categoryId = getOrCreateCategoryIdByTitle(note.getAccountId(), note.getCategory());
getNoteDao().updateCategory(note.getId(), categoryId);
getCategoryDao().removeEmptyCategory(note.getAccountId());
if (callback != null) {
syncHelper.addCallbackPush(ssoAccount, callback);
}
syncHelper.scheduleSync(ssoAccount, true);
}
}

View file

@ -1,5 +1,8 @@
package it.niedermann.owncloud.notes.persistence.dao;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import androidx.annotation.NonNull;
import androidx.room.Dao;
import androidx.room.Insert;
@ -27,4 +30,5 @@ public interface CategoryDao {
@Query("SELECT id FROM CategoryEntity WHERE accountId = :accountId AND title = :title")
Long getCategoryIdByTitle(long accountId, @NonNull String title);
}

View file

@ -1,5 +1,7 @@
package it.niedermann.owncloud.notes.persistence.dao;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
@ -30,6 +32,9 @@ public interface NoteDao {
@Query("UPDATE NoteEntity SET status = :status WHERE id = :id")
void updateStatus(long id, DBStatus status);
@Query("UPDATE NoteEntity SET category_id = :categoryId WHERE id = :id")
void updateCategory(long id, long categoryId);
/**
* Gets all the remoteIds of all not deleted notes of an account
*
@ -51,4 +56,15 @@ public interface NoteDao {
@Query("SELECT favorite, COUNT(*) FROM NoteEntity WHERE status != \"LOCAL_DELETED\" AND accountId = :accountId GROUP BY favorite ORDER BY favorite")
Map<String, Integer> getFavoritesCount(long accountId);
/**
* Returns a list of all Notes in the Database which were modified locally
*
* @return {@link List<DBNote>}
*/
@Query("SELECT * FROM NoteEntity WHERE status != \"VOID\" AND accountId = :accountId")
List<NoteEntity> getLocalModifiedNotes(long accountId);
@Query("SELECT * FROM NoteEntity WHERE status != \"LOCAL_DELETED\" AND accountId = :accountId ORDER BY modified DESC LIMIT 4")
List<NoteEntity> getRecentNotes(long accountId);
}