FileDocCategorySizeDatePackage
ExceptionBrowser.javaAPI DocAndroid 1.5 API5613Wed May 06 22:41:08 BST 2009com.android.development

ExceptionBrowser.java

/*
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

package com.android.development;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.ContentObserver;
import android.database.DataSetObserver;
import android.graphics.Typeface;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Checkin;
import android.server.data.CrashData;
import android.server.data.ThrowableData;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent;
import android.widget.*;

import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

/**
 *
 *
 */
public class ExceptionBrowser extends ListActivity {
    /** Logging identifier. */
    private static final String TAG = "ExceptionBrowser";

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        Cursor cursor = getContentResolver().query(
                Checkin.Crashes.CONTENT_URI,
                new String[] { Checkin.Crashes._ID, Checkin.Crashes.DATA },
                null, null, null);

        if (cursor != null) {
            startManagingCursor(cursor);

            setListAdapter(new CursorAdapter(this, cursor, true) {
                public View newView(Context context, Cursor c, ViewGroup v) {
                    return new CrashListItem(context);
                }

                public void bindView(View view, Context c, Cursor cursor) {
                    CrashListItem item = (CrashListItem) view;
                    try {
                        String data = cursor.getString(1);
                        CrashData crash = new CrashData(
                            new DataInputStream(
                                new ByteArrayInputStream(
                                    Base64.decodeBase64(data.getBytes()))));

                        ThrowableData exc = crash.getThrowableData();
                        item.setText(exc.getType() + ": " + exc.getMessage());
                        item.setCrashData(crash);
                    } catch (IOException e) {
                        item.setText("Invalid crash: " + e);
                        Log.e(TAG, "Invalid crash", e);
                    }
                }
            });
        } else {
            // No database, no exceptions, empty list.
            setListAdapter(new BaseAdapter() {
                public int getCount() {
                    return 0;
                }

                public Object getItem(int position) {
                    throw new AssertionError();
                }

                public long getItemId(int position) {
                    throw new AssertionError();
                }

                public View getView(int position, View convertView,
                        ViewGroup parent) {
                    throw new AssertionError();
                }
            });
        }
    }

    private static final int UPLOAD_ID = Menu.FIRST;
    private static final int CLEAR_ID = Menu.FIRST + 1;

    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(0, UPLOAD_ID, 0, R.string.menu_upload_exceptions);
        menu.add(0, CLEAR_ID, 0, R.string.menu_clear_exceptions);

        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle all of the possible menu actions.
        switch (item.getItemId()) {
            case UPLOAD_ID:
                sendBroadcast(new Intent(Checkin.TriggerIntent.ACTION));
                break;
            case CLEAR_ID:
                getContentResolver().delete(
                        Checkin.Crashes.CONTENT_URI, null, null);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    static class CrashListItem extends TextView {
        CrashData crashData = null;

        public CrashListItem(Context context) {
            super(context);
            setTextSize(10);
            setTypeface(Typeface.MONOSPACE);
        }

        public CrashData getCrashData() {
            return crashData;
        }

        public void setCrashData(CrashData crashData) {
            this.crashData = crashData;
        }
    }

    @Override
    protected void onListItemClick(ListView l, View view, int pos, long id) {
        // TODO: Use a generic VIEW action on the crash's content URI.
        CrashData crash = ((CrashListItem) view).getCrashData();
        if (crash != null) {
            Intent intent = new Intent();
            intent.setClass(this, StacktraceViewer.class);
            intent.putExtra(
                    CrashData.class.getName(),
                    crash.getThrowableData().toString());
            startActivity(intent);
        }
    }
}