mirror of
https://github.com/etesync/android
synced 2024-12-23 15:18:14 +00:00
OOM handling, DB transactions, calandar VISIBLE, service refresh notification
* handle and show OutOfMemoryErrors correctly (they're not Exceptions) * use db.beginTransactionNonExclusive() because WAL is enabled * set calendar VISIBLE=1 AND SYNC=1 only at creation and not at every sync * update PendingIntent of service refresh notification
This commit is contained in:
parent
2280f899ee
commit
c6aed90c96
@ -22,6 +22,8 @@ import android.database.sqlite.SQLiteDatabase;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v7.app.NotificationCompat;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@ -274,7 +276,7 @@ public class DavService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.beginTransaction();
|
db.beginTransactionNonExclusive();
|
||||||
saveHomeSets(homeSets);
|
saveHomeSets(homeSets);
|
||||||
saveCollections(collections.values());
|
saveCollections(collections.values());
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
@ -288,7 +290,7 @@ public class DavService extends Service {
|
|||||||
App.log.log(Level.SEVERE, "Couldn't refresh collection list", e);
|
App.log.log(Level.SEVERE, "Couldn't refresh collection list", e);
|
||||||
|
|
||||||
Intent debugIntent = new Intent(DavService.this, DebugInfoActivity.class);
|
Intent debugIntent = new Intent(DavService.this, DebugInfoActivity.class);
|
||||||
debugIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);
|
debugIntent.putExtra(DebugInfoActivity.KEY_THROWABLE, e);
|
||||||
if (account != null)
|
if (account != null)
|
||||||
debugIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
debugIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
||||||
|
|
||||||
@ -298,7 +300,7 @@ public class DavService extends Service {
|
|||||||
.setLargeIcon(((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
|
.setLargeIcon(((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
|
||||||
.setContentTitle(getString(R.string.dav_service_refresh_failed))
|
.setContentTitle(getString(R.string.dav_service_refresh_failed))
|
||||||
.setContentText(getString(R.string.dav_service_refresh_couldnt_refresh))
|
.setContentText(getString(R.string.dav_service_refresh_couldnt_refresh))
|
||||||
.setContentIntent(PendingIntent.getActivity(DavService.this, 0, debugIntent, 0))
|
.setContentIntent(PendingIntent.getActivity(DavService.this, 0, debugIntent, PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
.build();
|
.build();
|
||||||
nm.notify(Constants.NOTIFICATION_REFRESH_COLLECTIONS, notify);
|
nm.notify(Constants.NOTIFICATION_REFRESH_COLLECTIONS, notify);
|
||||||
} finally {
|
} finally {
|
||||||
@ -333,6 +335,7 @@ public class DavService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private Account account() {
|
private Account account() {
|
||||||
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.ACCOUNT_NAME }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.ACCOUNT_NAME }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
||||||
if (cursor.moveToNext()) {
|
if (cursor.moveToNext()) {
|
||||||
@ -341,6 +344,7 @@ public class DavService extends Service {
|
|||||||
throw new IllegalArgumentException("Service not found");
|
throw new IllegalArgumentException("Service not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private String serviceType() {
|
private String serviceType() {
|
||||||
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.SERVICE }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.SERVICE }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
||||||
if (cursor.moveToNext())
|
if (cursor.moveToNext())
|
||||||
@ -349,6 +353,7 @@ public class DavService extends Service {
|
|||||||
throw new IllegalArgumentException("Service not found");
|
throw new IllegalArgumentException("Service not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private HttpUrl readPrincipal() {
|
private HttpUrl readPrincipal() {
|
||||||
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.PRINCIPAL }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.PRINCIPAL }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
||||||
if (cursor.moveToNext()) {
|
if (cursor.moveToNext()) {
|
||||||
@ -359,6 +364,7 @@ public class DavService extends Service {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private Set<HttpUrl> readHomeSets() {
|
private Set<HttpUrl> readHomeSets() {
|
||||||
Set<HttpUrl> homeSets = new LinkedHashSet<>();
|
Set<HttpUrl> homeSets = new LinkedHashSet<>();
|
||||||
@Cleanup Cursor cursor = db.query(HomeSets._TABLE, new String[] { HomeSets.URL }, HomeSets.SERVICE_ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
@Cleanup Cursor cursor = db.query(HomeSets._TABLE, new String[] { HomeSets.URL }, HomeSets.SERVICE_ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
|
||||||
@ -377,6 +383,7 @@ public class DavService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private Map<HttpUrl, CollectionInfo> readCollections() {
|
private Map<HttpUrl, CollectionInfo> readCollections() {
|
||||||
Map<HttpUrl, CollectionInfo> collections = new LinkedHashMap<>();
|
Map<HttpUrl, CollectionInfo> collections = new LinkedHashMap<>();
|
||||||
@Cleanup Cursor cursor = db.query(Collections._TABLE, null, Collections.SERVICE_ID + "=?", new String[]{String.valueOf(service)}, null, null, null);
|
@Cleanup Cursor cursor = db.query(Collections._TABLE, null, Collections.SERVICE_ID + "=?", new String[]{String.valueOf(service)}, null, null, null);
|
||||||
|
@ -80,6 +80,10 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
|
|||||||
values.put(Calendars.ACCOUNT_TYPE, account.type);
|
values.put(Calendars.ACCOUNT_TYPE, account.type);
|
||||||
values.put(Calendars.OWNER_ACCOUNT, account.name);
|
values.put(Calendars.OWNER_ACCOUNT, account.name);
|
||||||
|
|
||||||
|
// flag as visible & synchronizable at creation, might be changed by user at any time
|
||||||
|
values.put(Calendars.VISIBLE, 1);
|
||||||
|
values.put(Calendars.SYNC_EVENTS, 1);
|
||||||
|
|
||||||
return create(account, provider, values);
|
return create(account, provider, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +106,6 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
|
|||||||
values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
|
values.put(Calendars.CAN_ORGANIZER_RESPOND, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
values.put(Calendars.SYNC_EVENTS, 1);
|
|
||||||
values.put(Calendars.VISIBLE, 1);
|
|
||||||
if (!TextUtils.isEmpty(info.timeZone)) {
|
if (!TextUtils.isEmpty(info.timeZone)) {
|
||||||
VTimeZone timeZone = DateUtils.parseVTimeZone(info.timeZone);
|
VTimeZone timeZone = DateUtils.parseVTimeZone(info.timeZone);
|
||||||
if (timeZone != null && timeZone.getTimeZoneId() != null)
|
if (timeZone != null && timeZone.getTimeZoneId() != null)
|
||||||
|
@ -9,14 +9,12 @@ package at.bitfire.davdroid.syncadapter;
|
|||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
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.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v7.app.NotificationCompat;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -46,7 +44,6 @@ import at.bitfire.davdroid.InvalidAccountException;
|
|||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import at.bitfire.davdroid.resource.LocalCollection;
|
import at.bitfire.davdroid.resource.LocalCollection;
|
||||||
import at.bitfire.davdroid.resource.LocalResource;
|
import at.bitfire.davdroid.resource.LocalResource;
|
||||||
import at.bitfire.davdroid.ui.AccountActivity;
|
|
||||||
import at.bitfire.davdroid.ui.AccountSettingsActivity;
|
import at.bitfire.davdroid.ui.AccountSettingsActivity;
|
||||||
import at.bitfire.davdroid.ui.DebugInfoActivity;
|
import at.bitfire.davdroid.ui.DebugInfoActivity;
|
||||||
import at.bitfire.ical4android.CalendarStorageException;
|
import at.bitfire.ical4android.CalendarStorageException;
|
||||||
@ -215,7 +212,7 @@ abstract public class SyncManager {
|
|||||||
detailsIntent.putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account);
|
detailsIntent.putExtra(AccountSettingsActivity.EXTRA_ACCOUNT, account);
|
||||||
} else {
|
} else {
|
||||||
detailsIntent = new Intent(context, DebugInfoActivity.class);
|
detailsIntent = new Intent(context, DebugInfoActivity.class);
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_EXCEPTION, e);
|
detailsIntent.putExtra(DebugInfoActivity.KEY_THROWABLE, e);
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
detailsIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority);
|
detailsIntent.putExtra(DebugInfoActivity.KEY_AUTHORITY, authority);
|
||||||
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase);
|
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase);
|
||||||
|
@ -197,7 +197,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
|
|||||||
OpenHelper dbHelper = new OpenHelper(AccountActivity.this);
|
OpenHelper dbHelper = new OpenHelper(AccountActivity.this);
|
||||||
try {
|
try {
|
||||||
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
SQLiteDatabase db = dbHelper.getWritableDatabase();
|
||||||
db.beginTransaction();
|
db.beginTransactionNonExclusive();
|
||||||
|
|
||||||
if (list.getChoiceMode() == AbsListView.CHOICE_MODE_SINGLE) {
|
if (list.getChoiceMode() == AbsListView.CHOICE_MODE_SINGLE) {
|
||||||
// disable all other collections
|
// disable all other collections
|
||||||
|
@ -17,19 +17,13 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Loader;
|
import android.content.Loader;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.DatabaseUtils;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.database.sqlite.SQLiteException;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.support.v4.database.DatabaseUtilsCompat;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -55,7 +49,7 @@ import lombok.Cleanup;
|
|||||||
|
|
||||||
public class DebugInfoActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
|
public class DebugInfoActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
|
||||||
public static final String
|
public static final String
|
||||||
KEY_EXCEPTION = "exception",
|
KEY_THROWABLE = "throwable",
|
||||||
KEY_LOGS = "logs",
|
KEY_LOGS = "logs",
|
||||||
KEY_ACCOUNT = "account",
|
KEY_ACCOUNT = "account",
|
||||||
KEY_AUTHORITY = "authority",
|
KEY_AUTHORITY = "authority",
|
||||||
@ -151,14 +145,14 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String loadInBackground() {
|
public String loadInBackground() {
|
||||||
Exception exception = null;
|
Throwable throwable = null;
|
||||||
String logs = null,
|
String logs = null,
|
||||||
authority = null;
|
authority = null;
|
||||||
Account account = null;
|
Account account = null;
|
||||||
int phase = -1;
|
int phase = -1;
|
||||||
|
|
||||||
if (extras != null) {
|
if (extras != null) {
|
||||||
exception = (Exception)extras.getSerializable(KEY_EXCEPTION);
|
throwable = (Throwable)extras.getSerializable(KEY_THROWABLE);
|
||||||
logs = extras.getString(KEY_LOGS);
|
logs = extras.getString(KEY_LOGS);
|
||||||
account = extras.getParcelable(KEY_ACCOUNT);
|
account = extras.getParcelable(KEY_ACCOUNT);
|
||||||
authority = extras.getString(KEY_AUTHORITY);
|
authority = extras.getString(KEY_AUTHORITY);
|
||||||
@ -176,17 +170,17 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
|
|||||||
if (authority != null)
|
if (authority != null)
|
||||||
report.append("Authority: ").append(authority).append("\n");
|
report.append("Authority: ").append(authority).append("\n");
|
||||||
|
|
||||||
if (exception instanceof HttpException) {
|
if (throwable instanceof HttpException) {
|
||||||
HttpException http = (HttpException)exception;
|
HttpException http = (HttpException)throwable;
|
||||||
if (http.request != null)
|
if (http.request != null)
|
||||||
report.append("\nHTTP REQUEST:\n").append(http.request).append("\n\n");
|
report.append("\nHTTP REQUEST:\n").append(http.request).append("\n\n");
|
||||||
if (http.response != null)
|
if (http.response != null)
|
||||||
report.append("HTTP RESPONSE:\n").append(http.response).append("\n");
|
report.append("HTTP RESPONSE:\n").append(http.response).append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exception != null)
|
if (throwable != null)
|
||||||
report .append("\nEXCEPTION:\n")
|
report .append("\nEXCEPTION:\n")
|
||||||
.append(ExceptionUtils.getStackTrace(exception));
|
.append(ExceptionUtils.getStackTrace(throwable));
|
||||||
|
|
||||||
if (logs != null)
|
if (logs != null)
|
||||||
report.append("\nLOGS:\n").append(logs).append("\n");
|
report.append("\nLOGS:\n").append(logs).append("\n");
|
||||||
|
@ -57,7 +57,7 @@ public class ExceptionInfoFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Intent intent = new Intent(getContext(), DebugInfoActivity.class);
|
Intent intent = new Intent(getContext(), DebugInfoActivity.class);
|
||||||
intent.putExtra(DebugInfoActivity.KEY_EXCEPTION, exception);
|
intent.putExtra(DebugInfoActivity.KEY_THROWABLE, exception);
|
||||||
if (account != null)
|
if (account != null)
|
||||||
intent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
intent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
Loading…
Reference in New Issue
Block a user