1
0
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:
Ricki Hirner 2016-03-31 12:21:58 +02:00
parent 2280f899ee
commit c6aed90c96
6 changed files with 24 additions and 24 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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");

View File

@ -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);