Add SQLite dump to debug report

This commit is contained in:
Ricki Hirner 2016-03-18 19:02:27 +01:00
parent 730a875e23
commit 9dce028f31
7 changed files with 145 additions and 71 deletions

View file

@ -23,7 +23,6 @@ public class Service {
service.accountName = values.getAsString(ServiceDB.Services.ACCOUNT_NAME);
service.service = values.getAsString(ServiceDB.Services.SERVICE);
service.principal = values.getAsString(ServiceDB.Services.PRINCIPAL);
//FIXME service.lastRefresh = values.getAsLong(ServiceDB.Services.LAST_REFRESH);
return service;
}

View file

@ -9,11 +9,14 @@
package at.bitfire.davdroid.model;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import at.bitfire.davdroid.App;
import lombok.Cleanup;
public class ServiceDB {
@ -23,8 +26,7 @@ public class ServiceDB {
ID = "_id",
ACCOUNT_NAME = "accountName",
SERVICE = "service",
PRINCIPAL = "principal",
LAST_REFRESH = "lastRefresh";
PRINCIPAL = "principal";
// allowed values for SERVICE column
public static final String
@ -87,9 +89,8 @@ public class ServiceDB {
Services.ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Services.ACCOUNT_NAME + " TEXT NOT NULL," +
Services.SERVICE + " TEXT NOT NULL," +
Services.PRINCIPAL + " TEXT NULL, " +
Services.LAST_REFRESH + " INTEGER NULL" +
")");
Services.PRINCIPAL + " TEXT NULL" +
")");
db.execSQL("CREATE UNIQUE INDEX services_account ON " + Services._TABLE + " (" + Services.ACCOUNT_NAME + "," + Services.SERVICE + ")");
db.execSQL("CREATE TABLE " + HomeSets._TABLE + "(" +
@ -117,6 +118,53 @@ public class ServiceDB {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public void dump(StringBuilder sb) {
SQLiteDatabase db = getReadableDatabase();
db.beginTransactionNonExclusive();
// iterate through all tables
@Cleanup Cursor cursorTables = db.query("sqlite_master", new String[] { "name" }, "type='table'", null, null, null, null);
while (cursorTables.moveToNext()) {
String table = cursorTables.getString(0);
sb.append("\t").append(table).append("\n");
@Cleanup Cursor cursor = db.query(table, null, null, null, null, null, null);
// print columns
int cols = cursor.getColumnCount();
sb.append("\t\t| ");
for (int i = 0; i < cols; i++) {
sb.append(" ");
sb.append(cursor.getColumnName(i));
sb.append(" |");
}
sb.append("\n");
// print rows
while (cursor.moveToNext()) {
sb.append("\t\t| ");
for (int i = 0; i < cols; i++) {
sb.append(" ");
try {
String value = cursor.getString(i);
if (value != null)
sb.append(value
.replace("\r", "<CR>")
.replace("\n", "<LF>"));
else
sb.append("<null>");
} catch (SQLiteException e) {
sb.append("<unprintable>");
}
sb.append(" |");
}
sb.append("\n");
}
}
db.endTransaction();
}
}
}

View file

@ -7,50 +7,51 @@
*/
package at.bitfire.davdroid.syncadapter;
import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.NotificationCompat;
import android.text.TextUtils;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.exception.ConflictException;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.exception.PreconditionFailedException;
import at.bitfire.dav4android.exception.ServiceUnavailableException;
import at.bitfire.dav4android.exception.UnauthorizedException;
import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetETag;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.HttpClient;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.LocalCollection;
import at.bitfire.davdroid.resource.LocalResource;
import at.bitfire.davdroid.ui.AccountActivity;
import at.bitfire.davdroid.ui.DebugInfoActivity;
import at.bitfire.ical4android.CalendarStorageException;
import at.bitfire.vcard4android.ContactsStorageException;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.exception.ConflictException;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.exception.PreconditionFailedException;
import at.bitfire.dav4android.exception.ServiceUnavailableException;
import at.bitfire.dav4android.exception.UnauthorizedException;
import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetETag;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.HttpClient;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.resource.LocalCollection;
import at.bitfire.davdroid.resource.LocalResource;
import at.bitfire.davdroid.ui.AccountActivity;
import at.bitfire.davdroid.ui.DebugInfoActivity;
import at.bitfire.ical4android.CalendarStorageException;
import at.bitfire.vcard4android.ContactsStorageException;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
abstract public class SyncManager {
@ -218,14 +219,12 @@ abstract public class SyncManager {
detailsIntent.putExtra(DebugInfoActivity.KEY_PHASE, syncPhase);
}
Notification.Builder builder = new Notification.Builder(context);
Notification notification;
builder.setSmallIcon(R.drawable.ic_launcher)
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder .setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getSyncErrorTitle())
.setContentIntent(PendingIntent.getActivity(context, notificationId, detailsIntent, PendingIntent.FLAG_UPDATE_CURRENT));
if (Build.VERSION.SDK_INT >= 20)
builder.setLocalOnly(true);
.setContentIntent(PendingIntent.getActivity(context, notificationId, detailsIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setLocalOnly(true);
try {
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);
@ -235,14 +234,7 @@ abstract public class SyncManager {
// should never happen
}
if (Build.VERSION.SDK_INT >= 16) {
if (Build.VERSION.SDK_INT >= 21)
builder.setCategory(Notification.CATEGORY_ERROR);
notification = builder.build();
} else {
notification = builder.getNotification();
}
notificationManager.notify(account.name, notificationId, notification);
notificationManager.notify(account.name, notificationId, builder.build());
}
}

View file

@ -50,6 +50,16 @@ public class AccountsActivity extends AppCompatActivity implements NavigationVie
NavigationView navigationView = (NavigationView)findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
if (savedInstanceState == null && !getPackageName().equals(getCallingPackage())) {
final String installedFrom = installedFrom();
if (installedFrom == null || installedFrom.startsWith("org.fdroid"))
getSupportFragmentManager().beginTransaction()
.add(new DonateDialogFragment(), null)
.commit();
else if ("com.android.vending".equals(installedFrom))
/* TODO Play Store Dialog */;
}
}
@Override
@ -81,4 +91,13 @@ public class AccountsActivity extends AppCompatActivity implements NavigationVie
drawer.closeDrawer(GravityCompat.START);
return true;
}
private String installedFrom() {
try {
return getPackageManager().getInstallerPackageName(getPackageName());
} catch(IllegalArgumentException e) {
return null;
}
}
}

View file

@ -17,11 +17,16 @@ import android.content.Context;
import android.content.Intent;
import android.content.Loader;
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.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.support.v4.database.DatabaseUtilsCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
@ -43,6 +48,8 @@ import at.bitfire.davdroid.App;
import at.bitfire.davdroid.BuildConfig;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.ServiceDB;
import lombok.Cleanup;
public class DebugInfoActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
public static final String
@ -57,6 +64,8 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
TextView tvReport;
String report;
File reportFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -86,7 +95,7 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
if (report.length() > MAX_INLINE_REPORT_LENGTH)
// report is too long for inline text, send it as an attachment
try {
File reportFile = File.createTempFile("davdroid-debug", ".txt", getExternalCacheDir());
reportFile = File.createTempFile("davdroid-debug", ".txt", getExternalCacheDir());
App.log.fine("Writing debug info to " + reportFile.getAbsolutePath());
FileWriter writer = new FileWriter(reportFile);
writer.write(report);
@ -217,6 +226,11 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
}
report.append("\n");
report.append("SQLITE DUMP\n");
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
dbHelper.dump(report);
report.append("\n");
try {
report.append(
"SYSTEM INFORMATION\n" +

View file

@ -8,12 +8,13 @@
package at.bitfire.davdroid.ui;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
@ -23,6 +24,7 @@ public class DonateDialogFragment extends DialogFragment {
public DonateDialogFragment() {
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
setCancelable(false);
@ -36,7 +38,7 @@ public class DonateDialogFragment extends DialogFragment {
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build()));
}
})
.setNegativeButton(R.string.donate_later, new DialogInterface.OnClickListener() {
.setNeutralButton(R.string.donate_later, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();

View file

@ -8,10 +8,10 @@
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"