mirror of
https://github.com/etesync/android
synced 2025-07-12 17:48:17 +00:00
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
This commit is contained in:
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 Cursor cursor = db.query(
|
@Cleanup OpenHelper dbHelper = new OpenHelper(getContext());
|
||||||
Services._TABLE,
|
SQLiteDatabase db = dbHelper.getReadableDatabase();
|
||||||
new String[] { Services.ID, Services.SERVICE },
|
|
||||||
Services.ACCOUNT_NAME + "=?", new String[] { account.name },
|
|
||||||
null, null, null);
|
|
||||||
|
|
||||||
if (cursor.getCount() == 0)
|
@Cleanup Cursor cursor = db.query(
|
||||||
// no services, account not useable
|
Services._TABLE,
|
||||||
return null;
|
new String[] { Services.ID, Services.SERVICE },
|
||||||
|
Services.ACCOUNT_NAME + "=?", new String[] { account.name },
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
if (cursor.getCount() == 0)
|
||||||
long id = cursor.getLong(0);
|
// no services, account not useable
|
||||||
String service = cursor.getString(1);
|
return null;
|
||||||
if (Services.SERVICE_CARDDAV.equals(service)) {
|
|
||||||
info.carddav = new AccountInfo.ServiceInfo();
|
|
||||||
info.carddav.id = id;
|
|
||||||
info.carddav.refreshing = davService.isRefreshing(id) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY);
|
|
||||||
info.carddav.hasHomeSets = hasHomeSets(db, id);
|
|
||||||
info.carddav.collections = readCollections(db, id);
|
|
||||||
|
|
||||||
} else if (Services.SERVICE_CALDAV.equals(service)) {
|
while (cursor.moveToNext()) {
|
||||||
info.caldav = new AccountInfo.ServiceInfo();
|
long id = cursor.getLong(0);
|
||||||
info.caldav.id = id;
|
String service = cursor.getString(1);
|
||||||
info.caldav.refreshing = davService.isRefreshing(id) ||
|
if (Services.SERVICE_CARDDAV.equals(service)) {
|
||||||
ContentResolver.isSyncActive(account, CalendarContract.AUTHORITY) ||
|
info.carddav = new AccountInfo.ServiceInfo();
|
||||||
ContentResolver.isSyncActive(account, TaskProvider.ProviderName.OpenTasks.authority);
|
info.carddav.id = id;
|
||||||
info.caldav.hasHomeSets = hasHomeSets(db, id);
|
info.carddav.refreshing = davService.isRefreshing(id) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY);
|
||||||
info.caldav.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();
|
||||||
|
info.caldav.id = id;
|
||||||
|
info.caldav.refreshing = davService.isRefreshing(id) ||
|
||||||
|
ContentResolver.isSyncActive(account, CalendarContract.AUTHORITY) ||
|
||||||
|
ContentResolver.isSyncActive(account, TaskProvider.ProviderName.OpenTasks.authority);
|
||||||
|
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…
Reference in New Issue
Block a user