更新appwidget,sqlite时出现问题

时间:2012-08-15 09:19:02

标签: android service sqlite widget

我有更新appwidget的问题。这是一个简单的小部件,它使用服务来更新小部件并从db(sqlite)获取引用并在主屏幕上显示它。

在日志中我看到引号已插入db。它们由方法

返回
List<Quote> contacts = quoteSeeker.getAllQuotes();

然后显示在日志中:

Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

之后出现了这些警告和错误。可能是什么问题?

来自LOGCAT的日志:

08-15 10:56:18.295: I/service jarek(3061): Called
08-15 10:56:18.335: I/JARO TEST(3061): Called
08-15 10:56:18.335: D/Insert:(3061): Inserting ..
08-15 10:56:19.280: D/Reading:(3061): Reading all contacts..
08-15 10:56:19.335: D/Name:(3061): Id: 1 ,Name: Ravi ,Phone: 9100000000
08-15 10:56:19.335: D/Name:(3061): Id: 2 ,Name: Srinivas ,Phone: 9199999999
08-15 10:56:19.335: D/Name:(3061): Id: 3 ,Name: Tommy ,Phone: 9522222222
08-15 10:56:19.340: D/Name:(3061): Id: 4 ,Name: Karthik ,Phone: 9533333333
08-15 10:56:19.340: D/Name:(3061): Id: 5 ,Name: Darek ,Phone: DAREKDAREK
08-15 10:56:19.340: D/Name:(3061): Id: 6 ,Name: Ravi ,Phone: 9100000000
08-15 10:56:19.340: D/Name:(3061): Id: 7 ,Name: Srinivas ,Phone: 9199999999
08-15 10:56:19.345: D/Name:(3061): Id: 8 ,Name: Tommy ,Phone: 9522222222
08-15 10:56:19.345: D/Name:(3061): Id: 9 ,Name: Karthik ,Phone: 9533333333
08-15 10:56:19.345: D/Name:(3061): Id: 10 ,Name: Darek ,Phone: DAREKDAREK
08-15 10:56:19.345: D/Name:(3061): Id: 11 ,Name: Ravi ,Phone: 9100000000
08-15 10:56:19.350: D/Name:(3061): Id: 12 ,Name: Srinivas ,Phone: 9199999999
08-15 10:56:19.355: D/Name:(3061): Id: 13 ,Name: Tommy ,Phone: 9522222222
08-15 10:56:19.355: D/Name:(3061): Id: 14 ,Name: Karthik ,Phone: 9533333333
08-15 10:56:19.355: D/Name:(3061): Id: 15 ,Name: Darek ,Phone: DAREKDAREK
08-15 10:56:19.360: D/Name:(3061): Id: 16 ,Name: Ravi ,Phone: 9100000000
08-15 10:56:19.365: D/Name:(3061): Id: 17 ,Name: Srinivas ,Phone: 9199999999
08-15 10:56:19.365: D/Name:(3061): Id: 18 ,Name: Tommy ,Phone: 9522222222
08-15 10:56:19.365: D/Name:(3061): Id: 19 ,Name: Karthik ,Phone: 9533333333
08-15 10:56:19.370: D/Name:(3061): Id: 20 ,Name: Darek ,Phone: DAREKDAREK
08-15 10:56:19.375: W/JARO TEST(3061): From Intent1
08-15 10:56:19.380: W/JARO TEST(3061): Direct1
08-15 10:56:19.545: D/AndroidRuntime(3061): Shutting down VM
08-15 10:56:19.545: W/dalvikvm(3061): threadid=1: thread exiting with uncaught exception (group=0x4001d7f0)
08-15 10:56:19.580: E/AndroidRuntime(3061): FATAL EXCEPTION: main
08-15 10:56:19.580: E/AndroidRuntime(3061): java.lang.RuntimeException: Unable to start service beautiful.quotes.UpdateWidgetService@4643d410 with Intent { cmp=beautiful.quotes/.UpdateWidgetService (has extras) }: java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT  * FROM quotes) 
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3070)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.app.ActivityThread.access$3600(ActivityThread.java:125)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2096)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.os.Looper.loop(Looper.java:123)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.app.ActivityThread.main(ActivityThread.java:4641)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at java.lang.reflect.Method.invokeNative(Native Method)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at java.lang.reflect.Method.invoke(Method.java:521)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:638)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at dalvik.system.NativeStart.main(Native Method)
08-15 10:56:19.580: E/AndroidRuntime(3061): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT  * FROM quotes) 
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:34)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:67)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:285)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:266)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at beautiful.quotes.DBHandler.getQuotesCount(DBHandler.java:114)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at         beautiful.quotes.DBHandler.getRandomQuote(DBHandler.java:139)
08-15 10:56:19.580: E/AndroidRuntime(3061):     at                     beautiful.quotes.UpdateWidgetService.onStart(UpdateWidgetService.java:62)

代码: Android manifest.xml

  <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" android:debuggable="true">  
        <receiver android:name="BeautifulQuotesWidget">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider" 
                android:resource="@xml/beatiful_quotes" />
        </receiver>  
        <service android:name=".UpdateWidgetService"></service>    
    </application>

小部件的Xml:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" 
    android:minWidth="146dip"
    android:minHeight="72dip"
    android:updatePeriodMillis="180000"
    android:initialLayout="@layout/activity_beautiful_quotes"
/>

DBHelper:

public class DBHandler扩展了SQLiteOpenHelper {

    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 1;
    // Database Name
    private static final String DATABASE_NAME = "QuotesManager";
    // Contacts table name
    private static final String TABLE_QUOTES = "quotes";
    // Contacts Table Columns names
    private static final String KEY_ID = "id";
    private static final String KEY_AUTHOR = "author";
    private static final String KEY_DESCR = "description";
    private static final String LOG = "BAZA TEST";

    public DBHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        // TODO Auto-generated constructor stub
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
         String CREATE_QUOTES_TABLE = "CREATE TABLE " + TABLE_QUOTES + "("
                    + KEY_ID + " INTEGER PRIMARY KEY," + KEY_AUTHOR + " TEXT,"
                    + KEY_DESCR + " TEXT" + ")";
            db.execSQL(CREATE_QUOTES_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_QUOTES);
        // Create tables again
        onCreate(db);
    }

    // Adding new quote
    public void addQuote(Quote quote) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_AUTHOR, quote.getAuthor()); // Author
        values.put(KEY_DESCR, quote.getDescription()); // Description

        // Inserting Row
        db.insert(TABLE_QUOTES, null, values);
        db.close(); // Closing database connection
    }

    // Getting single quote
    public Quote getQuote(int id) {
        SQLiteDatabase db = this.getReadableDatabase();
        Log.i(LOG, "Baza danych");
        Cursor cursor = db.query(TABLE_QUOTES, new String[] { KEY_ID,
                KEY_AUTHOR, KEY_DESCR }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Quote quote = new Quote(Integer.parseInt(cursor.getString(0)),
                cursor.getString(1), cursor.getString(2));
        // return quote
        return quote;   
    }

    // Getting All quotes
    public List<Quote> getAllQuotes() {
        List<Quote> quotesList = new ArrayList<Quote>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_QUOTES;

        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Quote quote = new Quote();
                quote.setID(Integer.parseInt(cursor.getString(0)));
                quote.setAuthor(cursor.getString(1));
                quote.setDescription(cursor.getString(2));
                // Adding contact to list
                quotesList.add(quote);
            } while (cursor.moveToNext());
        }
        // return contact list
        cursor.close();
        return quotesList;  
    }

    // Getting quotes count
    public int getQuotesCount() {
          String countQuery = "SELECT  * FROM " + TABLE_QUOTES;
            SQLiteDatabase db = this.getReadableDatabase();
            Cursor cursor = db.rawQuery(countQuery, null);
            cursor.close();
            // return count
            return cursor.getCount();
    }

    // Updating single quote
    public int updateQuote(Quote quote) {
            SQLiteDatabase db = this.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put(KEY_AUTHOR, quote.getAuthor());
            values.put(KEY_DESCR, quote.getDescription());
            // updating row
            return db.update(TABLE_QUOTES, values, KEY_ID + " = ?",
                    new String[] { String.valueOf(quote.getID()) });
}

    // Deleting single quote
    public void deleteQuote(Quote quote) {
           SQLiteDatabase db = this.getWritableDatabase();
            db.delete(TABLE_QUOTES, KEY_ID + " = ?",
                    new String[] { String.valueOf(quote.getID()) });
            db.close();
    }

    //Get random quote
    public Quote getRandomQuote(){
        SQLiteDatabase db = this.getReadableDatabase();
         int counts = getQuotesCount();
         Random rn = new Random();
         int id = rn.nextInt(counts);
        Cursor cursor = db.query(TABLE_QUOTES, new String[] { KEY_ID,
                KEY_AUTHOR, KEY_DESCR }, KEY_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Quote quote = new Quote(Integer.parseInt(cursor.getString(0)),
                cursor.getString(1), cursor.getString(2));
        // return quote
        return quote;
    }
}

服务:

public class UpdateWidgetService extends Service {
    private static final String LOG = "JARO TEST";
    DBHandler quoteSeeker;

    @Override
    public void onStart(Intent intent, int startId) {
        Log.i(LOG, "Called");
        // Create some random data
        quoteSeeker = new DBHandler(this);
         // Inserting Contacts
       Log.d("Insert: ", "Inserting ..");
       quoteSeeker.addQuote(new Quote("Ravi", "9100000000"));
       quoteSeeker.addQuote(new Quote("Srinivas", "9199999999"));
       quoteSeeker.addQuote(new Quote("Tommy", "9522222222"));
       quoteSeeker.close();
        quoteSeeker.addQuote(new Quote("Karthik", "9533333333"));
        quoteSeeker.addQuote(new Quote("Darek", "DAREKDAREK"));

        // Reading all contacts
        Log.d("Reading: ", "Reading all contacts..");
        List<Quote> contacts = quoteSeeker.getAllQuotes();       
        for (Quote cn : contacts) {
            String log = "Id: "+cn.getID()+" ,Name: " + cn.getAuthor() + " ,Phone: " + cn.getDescription();
                // Writing Contacts to log
        Log.d("Name: ", log);
    }
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
                .getApplicationContext());

        int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

        ComponentName thisWidget = new ComponentName(getApplicationContext(),
                BeautifulQuotesWidget.class);

        int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
        Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
        Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

        for (int widgetId : allWidgetIds) {
            // Create some random data
            int number = (new Random().nextInt(100));
            quoteSeeker = new DBHandler(this);
            Quote q1 = quoteSeeker.getRandomQuote();
            RemoteViews remoteViews = new RemoteViews(this
                    .getApplicationContext().getPackageName(),
                    R.layout.activity_beautiful_quotes);
            Log.w("WidgetExample", String.valueOf(number));
            // Set the text
            remoteViews.setTextViewText(R.id.author_name,
                    "Random: " + String.valueOf(q1.getAuthor()));
            remoteViews.setTextViewText(R.id.quote_descr,
                    "Descr: " + String.valueOf(q1.getDescription()));

            // Register an onClickListener
            Intent clickIntent = new Intent(this.getApplicationContext(),
                    BeautifulQuotesWidget.class);

            clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
                    allWidgetIds);

            PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.quote_descr, pendingIntent);
            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
        stopSelf();
        super.onStart(intent, startId);
    }
}

AppWidgetProvider

public class BeautifulQuotesWidget extends AppWidgetProvider{
    private static final String LOG = "service jarek";

        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            // To prevent any ANR timeouts, we perform the update in a service
        // Get all ids
            ComponentName thisWidget = new ComponentName(context, BeautifulQuotesWidget.class);
            int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

            // Build the intent to call the service
            Intent intent = new Intent(context.getApplicationContext(),
                    UpdateWidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

            Log.i(LOG, "Called");
            //context.startService(new Intent(context, UpdateService.class));
            // Update the widgets via the service
            context.startService(intent);
        }
}

1 个答案:

答案 0 :(得分:0)

关注UpdateWidgetService

的这两行
stopSelf();
super.onStart(intent, startId);

在第二行......你正在调用一个方法本身(递归)......通过调用stopSelf结束你的服务......

这就是问题......你正在调用你在上一行中销毁过的类的方法......

希望这会有所帮助...

如果您认为这回答了您的问题,请将其标记为“已接受”。这将提高您和我的声誉分数。