Android 4.0/4.1 fixes

* require API level 15 for TransactionTooLargeException
* use SQLite WAL only on API level 16+
* various database access, provider access and UI fixes
pull/2/head
Ricki Hirner 8 years ago
parent 4e87186dd8
commit 3813c1e0c8

@ -10,14 +10,14 @@ apply plugin: 'com.android.application'
android { android {
compileSdkVersion 24 compileSdkVersion 24
buildToolsVersion '24.0.2' buildToolsVersion '24.0.3'
defaultConfig { defaultConfig {
applicationId "at.bitfire.davdroid" applicationId "at.bitfire.davdroid"
minSdkVersion 14 minSdkVersion 15
targetSdkVersion 24 targetSdkVersion 24
versionCode 118 versionCode 119
buildConfigField "long", "buildTime", System.currentTimeMillis() + "L" buildConfigField "long", "buildTime", System.currentTimeMillis() + "L"
buildConfigField "boolean", "customCerts", "true" buildConfigField "boolean", "customCerts", "true"
@ -25,7 +25,7 @@ android {
productFlavors { productFlavors {
standard { standard {
versionName "1.3.2-ose" versionName "1.3.2.1-ose"
} }
} }

@ -14,7 +14,11 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build; import android.os.Build;
import android.support.annotation.RequiresApi;
import java.util.logging.Level;
import aQute.service.reporter.Messages;
import at.bitfire.davdroid.App; import at.bitfire.davdroid.App;
import lombok.Cleanup; import lombok.Cleanup;
@ -72,21 +76,19 @@ public class ServiceDB {
public OpenHelper(Context context) { public OpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
setWriteAheadLoggingEnabled(true);
} }
@Override @Override
public void onOpen(SQLiteDatabase db) { public void onOpen(SQLiteDatabase db) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) if (Build.VERSION.SDK_INT < 16)
db.setForeignKeyConstraintsEnabled(true);
else {
if (!db.enableWriteAheadLogging())
App.log.warning("Couldn't enable write-ahead logging");
db.execSQL("PRAGMA foreign_keys=ON;"); db.execSQL("PRAGMA foreign_keys=ON;");
} }
@Override
@RequiresApi(16)
public void onConfigure(SQLiteDatabase db) {
setWriteAheadLoggingEnabled(true);
db.setForeignKeyConstraintsEnabled(true);
} }
@Override @Override
@ -132,6 +134,7 @@ public class ServiceDB {
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// no different versions yet
} }

@ -9,14 +9,12 @@
package at.bitfire.davdroid.resource; package at.bitfire.davdroid.resource;
import android.accounts.Account; import android.accounts.Account;
import android.annotation.TargetApi;
import android.content.ContentProviderClient; import android.content.ContentProviderClient;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.provider.CalendarContract; import android.provider.CalendarContract;
import android.provider.CalendarContract.Calendars; import android.provider.CalendarContract.Calendars;
@ -85,7 +83,6 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
update(valuesFromCollectionInfo(info, updateColor)); update(valuesFromCollectionInfo(info, updateColor));
} }
@TargetApi(15)
private static ContentValues valuesFromCollectionInfo(CollectionInfo info, boolean withColor) { private static ContentValues valuesFromCollectionInfo(CollectionInfo info, boolean withColor) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Calendars.NAME, info.url); values.put(Calendars.NAME, info.url);
@ -108,10 +105,8 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(timeZone.getTimeZoneId().getValue())); values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(timeZone.getTimeZoneId().getValue()));
} }
values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT); values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT);
if (Build.VERSION.SDK_INT >= 15) { values.put(Calendars.ALLOWED_AVAILABILITY, StringUtils.join(new int[] { Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY }, ","));
values.put(Calendars.ALLOWED_AVAILABILITY, StringUtils.join(new int[] { Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY }, ",")); values.put(Calendars.ALLOWED_ATTENDEE_TYPES, StringUtils.join(new int[] { CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE }, ", "));
values.put(Calendars.ALLOWED_ATTENDEE_TYPES, StringUtils.join(new int[] { CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE }, ", "));
}
return values; return values;
} }

@ -68,8 +68,12 @@ public class LocalEvent extends AndroidEvent implements LocalResource {
event.uid = values.getAsString(COLUMN_UID); event.uid = values.getAsString(COLUMN_UID);
event.sequence = values.getAsInteger(COLUMN_SEQUENCE); event.sequence = values.getAsInteger(COLUMN_SEQUENCE);
if (values.getAsInteger(Events.IS_ORGANIZER) == 0) if (Build.VERSION.SDK_INT >= 17)
weAreOrganizer = false; weAreOrganizer = values.getAsInteger(Events.IS_ORGANIZER) != 0;
else {
String organizer = values.getAsString(Events.ORGANIZER);
weAreOrganizer = organizer == null || organizer.equals(calendar.account.name);
}
} }
@Override @Override

@ -10,7 +10,6 @@ package at.bitfire.davdroid.syncadapter;
import android.accounts.Account; import android.accounts.Account;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
@ -18,7 +17,6 @@ import android.content.ContentProviderClient;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SyncResult; import android.content.SyncResult;
import android.graphics.drawable.BitmapDrawable;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
@ -38,6 +36,8 @@ import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R; import at.bitfire.davdroid.R;
import at.bitfire.davdroid.ui.PermissionsActivity; import at.bitfire.davdroid.ui.PermissionsActivity;
//import com.android.vending.billing.IInAppBillingService;
public abstract class SyncAdapterService extends Service { public abstract class SyncAdapterService extends Service {
abstract protected AbstractThreadedSyncAdapter syncAdapter(); abstract protected AbstractThreadedSyncAdapter syncAdapter();

@ -355,14 +355,12 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
private static class AccountLoader extends AsyncTaskLoader<AccountInfo> implements DavService.RefreshingStatusListener, ServiceConnection, SyncStatusObserver { private static class AccountLoader extends AsyncTaskLoader<AccountInfo> implements DavService.RefreshingStatusListener, ServiceConnection, SyncStatusObserver {
private final Account account; private final Account account;
private final OpenHelper dbHelper;
private DavService.InfoBinder davService; private DavService.InfoBinder davService;
private Object syncStatusListener; private Object syncStatusListener;
public AccountLoader(Context context, Account account) { public AccountLoader(Context context, Account account) {
super(context); super(context);
this.account = account; this.account = account;
dbHelper = new OpenHelper(context);
} }
@Override @Override
@ -407,41 +405,39 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
@Override @Override
public AccountInfo loadInBackground() { public AccountInfo loadInBackground() {
AccountInfo info = new AccountInfo(); AccountInfo info = new AccountInfo();
try {
SQLiteDatabase db = dbHelper.getReadableDatabase(); @Cleanup OpenHelper dbHelper = new OpenHelper(getContext());
SQLiteDatabase db = dbHelper.getReadableDatabase();
@Cleanup Cursor cursor = db.query(
Services._TABLE, @Cleanup Cursor cursor = db.query(
new String[] { Services.ID, Services.SERVICE }, Services._TABLE,
Services.ACCOUNT_NAME + "=?", new String[] { account.name }, new String[] { Services.ID, Services.SERVICE },
null, null, null); Services.ACCOUNT_NAME + "=?", new String[] { account.name },
null, null, null);
if (cursor.getCount() == 0)
// no services, account not useable if (cursor.getCount() == 0)
return null; // no services, account not useable
return null;
while (cursor.moveToNext()) {
long id = cursor.getLong(0); while (cursor.moveToNext()) {
String service = cursor.getString(1); long id = cursor.getLong(0);
if (Services.SERVICE_CARDDAV.equals(service)) { String service = cursor.getString(1);
info.carddav = new AccountInfo.ServiceInfo(); if (Services.SERVICE_CARDDAV.equals(service)) {
info.carddav.id = id; info.carddav = new AccountInfo.ServiceInfo();
info.carddav.refreshing = davService.isRefreshing(id) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY); info.carddav.id = id;
info.carddav.hasHomeSets = hasHomeSets(db, id); info.carddav.refreshing = davService.isRefreshing(id) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY);
info.carddav.collections = readCollections(db, id); info.carddav.hasHomeSets = hasHomeSets(db, id);
info.carddav.collections = readCollections(db, id);
} else if (Services.SERVICE_CALDAV.equals(service)) {
info.caldav = new AccountInfo.ServiceInfo(); } else if (Services.SERVICE_CALDAV.equals(service)) {
info.caldav.id = id; info.caldav = new AccountInfo.ServiceInfo();
info.caldav.refreshing = davService.isRefreshing(id) || info.caldav.id = id;
ContentResolver.isSyncActive(account, CalendarContract.AUTHORITY) || info.caldav.refreshing = davService.isRefreshing(id) ||
ContentResolver.isSyncActive(account, TaskProvider.ProviderName.OpenTasks.authority); ContentResolver.isSyncActive(account, CalendarContract.AUTHORITY) ||
info.caldav.hasHomeSets = hasHomeSets(db, id); ContentResolver.isSyncActive(account, TaskProvider.ProviderName.OpenTasks.authority);
info.caldav.collections = readCollections(db, id); info.caldav.hasHomeSets = hasHomeSets(db, id);
} info.caldav.collections = readCollections(db, id);
} }
} finally {
dbHelper.close();
} }
return info; return info;
} }

@ -20,7 +20,6 @@ import at.bitfire.davdroid.App;
import at.bitfire.davdroid.R; import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.ServiceDB; import at.bitfire.davdroid.model.ServiceDB;
import at.bitfire.davdroid.model.Settings; import at.bitfire.davdroid.model.Settings;
import lombok.Cleanup;
public class AppSettingsActivity extends AppCompatActivity { public class AppSettingsActivity extends AppCompatActivity {

@ -15,6 +15,7 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@ -95,8 +96,6 @@ public class StartupDialogFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
setCancelable(false); setCancelable(false);
final ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Mode mode = Mode.valueOf(getArguments().getString(ARGS_MODE)); Mode mode = Mode.valueOf(getArguments().getString(ARGS_MODE));
switch (mode) { switch (mode) {
case BATTERY_OPTIMIZATIONS: case BATTERY_OPTIMIZATIONS:
@ -119,6 +118,7 @@ public class StartupDialogFragment extends DialogFragment {
.setNegativeButton(R.string.startup_dont_show_again, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.startup_dont_show_again, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Settings settings = new Settings(dbHelper.getWritableDatabase()); Settings settings = new Settings(dbHelper.getWritableDatabase());
settings.putBoolean(HINT_BATTERY_OPTIMIZATIONS, false); settings.putBoolean(HINT_BATTERY_OPTIMIZATIONS, false);
} }
@ -187,6 +187,7 @@ public class StartupDialogFragment extends DialogFragment {
.setNegativeButton(R.string.startup_dont_show_again, new DialogInterface.OnClickListener() { .setNegativeButton(R.string.startup_dont_show_again, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Settings settings = new Settings(dbHelper.getWritableDatabase()); Settings settings = new Settings(dbHelper.getWritableDatabase());
settings.putBoolean(HINT_OPENTASKS_NOT_INSTALLED, false); settings.putBoolean(HINT_OPENTASKS_NOT_INSTALLED, false);
} }

@ -17,7 +17,6 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;

@ -13,7 +13,7 @@
<item android:id="@+id/sync_now" <item android:id="@+id/sync_now"
android:icon="@drawable/ic_sync_dark" android:icon="@drawable/ic_sync_dark"
android:title="@string/account_synchronize_now" android:title="@string/account_synchronize_now"
app:showAsAction="ifRoom"/> app:showAsAction="always"/>
<item android:id="@+id/settings" <item android:id="@+id/settings"
android:icon="@drawable/ic_settings_dark" android:icon="@drawable/ic_settings_dark"
@ -21,6 +21,7 @@
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item android:id="@+id/delete_account" <item android:id="@+id/delete_account"
android:title="@string/account_delete"/> android:title="@string/account_delete"
app:showAsAction="never"/>
</menu> </menu>

@ -1 +1 @@
Subproject commit f6535874a9f1f399913dcb51bda1aa9affbb4c5a Subproject commit 85f4d947089ac3e0b7a61cbedfc69dd6ec7f235d

@ -1 +1 @@
Subproject commit 8c4776a6be83b641611c12e1a0e524b6435bcf9a Subproject commit 95a2761006f1c605ee277fa36b0d1aaa083c86bc
Loading…
Cancel
Save