I add a configure/settings Activity in my AppWidget and started gotting 
some problems. At first, I didn't knew what is the cause, so I commented 
some parts of the code to figure it out. So what I've found is that the 
AlarmManager code is causing it. I already tried changing simulator's 
version, cleared the project and everything. I'm dealing with this problem 
for almost 3 days...

Here are a screen shot showing it. Note that there are 2 widgets in the 
home screen, completely different, but both are the same! I mean... Both 
are my AppWidget, they should look as the lower one, but with 2 
TextViews... The 2 ImageButtons are there, but they don't always show. :/

http://www.flickr.com/photos/76149280@N08/8169290591/in/photostream?

So, my question is: what do I have to do to make it work? Do I have to 
create a "service", do I have to change same code, even use another thing 
instead of AlarmManager or what?

P.S.: I already asked on Stack Overflow ( 
http://stackoverflow.com/questions/13322168/alarmmanager-destroying-an-appwidget-android-sdk
 ), 
but noting...

Here go the codes.

* AppProviderInfo (small_widget_provider_info.xml)

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider 
xmlns:android="http://schemas.android.com/apk/res/android";
    android:initialLayout="@layout/widget_layout_small"
    android:minHeight="40dp"
    android:minWidth="250dp"
    android:updatePeriodMillis="86400000"
    android:configure="com.br.mcsoft.quotes.activity.SettingsActivity" >
</appwidget-provider>

* AppProvider (WidgetProviderSmall.java)

package com.br.mcsoft.quotes.provider;

import com.br.mcsoft.quotes.R;
import com.br.mcsoft.quotes.Adapters.DBAdapter;
import com.br.mcsoft.quotes.activity.QuoteActivity;
import com.br.mcsoft.quotes.model.Quote;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.RemoteViews;

public class WidgetProviderSmall extends AppWidgetProvider {
    private static final String TAG = "WidgetProviderSmall";

    public static final String URI_SCHEME = "widget_provider_small";

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        // super.onUpdate(context, appWidgetManager, appWidgetIds);
        System.out.println("Updatando...");
        final int n = appWidgetIds.length;
        for (int i = 0; i < n; i++) {
            System.out.println("Entrou no loop...");

            // Cria o RemoteViews
            RemoteViews rv = new RemoteViews(context.getPackageName(),
                    R.layout.widget_layout_small);

            // Atualiza os dados...
            try {
                DBAdapter db;
                db = new DBAdapter(context);
                db.open();
                Quote q = db.getRandomQuote();
                db.close();

                // Guarda o ID da citação...

                Editor configEditor = context.getSharedPreferences(
                        "QuoteWidgetSmall", 0).edit();
                configEditor
                        .putInt(String.format("QuoteId-%d", 
appWidgetIds[i]),
                                q.getId());
                configEditor.commit();
                System.out.println("Id: " + appWidgetIds[i]);
                System.out.println("Quote Id: " + q.getId());

                // Verifica o tamanho e trunca o texto da citação...
                String textQuote = "\"" + q.getQuote() + "\"";
                if (textQuote.length() > 110 + 10) {
                    textQuote = textQuote.substring(0, 110) + "...\" [...]";
                }

                System.out.println("Quote: " + q.getQuote());
                System.out.println("Author: " + q.getAuthor().getName());

                // Seta os campos...
                // rv.setTextViewText(R.id.txtWdgQuote, "\"" + q.getQuote() 
+
                // "\"");
                rv.setTextViewText(R.id.txtWdgQuote, textQuote);
                rv.setTextViewText(R.id.txtWdgAuthor, "— "
                        + q.getAuthor().getName());

                System.out.println("Setou os valores...");
            } catch (SQLException e) {
                Log.e(TAG, e.getMessage(), e);
            }

            // Adiciona o listener do evento do botão Next...
            Intent active = new Intent(context, WidgetProviderSmall.class);
            active.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            // onUpdate recebe um array de ints, então passa como array.
            active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
                    new int[] { appWidgetIds[i] });
            Uri data = Uri.withAppendedPath(
                    Uri.parse(URI_SCHEME + "://widget/id/"),
                    String.valueOf(appWidgetIds[i]));
            active.setData(data);
            PendingIntent actionPendingIntent = PendingIntent.getBroadcast(
                    context, appWidgetIds[i], active, 0);
            rv.setOnClickPendingIntent(R.id.ibtNext, actionPendingIntent);

            // Adiciona o listener do evento do clique no Widget...
            active = new Intent(context, WidgetProviderSmall.class);
            active.setAction(StaticHelper.ACTION_CLICK);
            // onReceive precisa apenas do Id em um int, então passa assim.
            active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    appWidgetIds[i]);
            data = Uri.withAppendedPath(
                    Uri.parse(URI_SCHEME + "://widget/id/"),
                    String.valueOf(appWidgetIds[i]));
            active.setData(data);
            actionPendingIntent = PendingIntent.getBroadcast(context,
                    appWidgetIds[i], active, 0);
            rv.setOnClickPendingIntent(R.id.laySmall, actionPendingIntent);

            /*
             * // Adiciona o listener do evento do botão Settings... active 
=
             * new Intent(context, WidgetProviderSmall.class);
             * active.setAction(StaticHelper.ACTION_SETTINGS);
             * actionPendingIntent = PendingIntent.getBroadcast(context, 0,
             * active, 0); rv.setOnClickPendingIntent(R.id.ibtSettings,
             * actionPendingIntent);
             */

            // Salva tudo
            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
            // Atualiza os dados...
        }
        System.out.println("Terminou o update...");
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (intent.getAction().equals(StaticHelper.ACTION_CLICK)) {
            Bundle extras = intent.getExtras();
            if (extras != null) {
                int widgetId = extras.getInt(
                        AppWidgetManager.EXTRA_APPWIDGET_ID,
                        AppWidgetManager.INVALID_APPWIDGET_ID);
                if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                    // Pega o quote Id
                    SharedPreferences config = context.getSharedPreferences(
                            "QuoteWidgetSmall", 0);
                    int quoteId = config.getInt(
                            String.format("QuoteId-%d", widgetId), -1);
                    System.out.println("Id: " + widgetId);
                    System.out.println("Quote Id: " + quoteId);

                    Intent i = new Intent(context, QuoteActivity.class);
                    Bundle b = new Bundle();
                    b.putInt("QuoteId", quoteId);
                    i.putExtras(b);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(i);
                } else {
                    System.out.println("Id ZERADO!");
                }
            }
        } else if (intent.getAction().equals(StaticHelper.ACTION_SETTINGS)) 
{
            // Chama a tela de settings...
            System.out.println("Chamou o config...");
        }
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        System.out.println("Ih! OnDelete!");
        int widgetId;
        final int n = appWidgetIds.length;
        for (int i = 0; i < n; i++) {
            System.out.println("Deletando...");
            widgetId = appWidgetIds[i];

            Intent widgetUpdate = new Intent();
            widgetUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
                    new int[] { widgetId });
            
widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

            PendingIntent newPending = PendingIntent.getBroadcast(context,
                    widgetId, widgetUpdate, 
PendingIntent.FLAG_UPDATE_CURRENT);

            // Para o alarme...
            AlarmManager alarms = (AlarmManager) context
                    .getSystemService(Context.ALARM_SERVICE);
            alarms.cancel(newPending);

            // Remove o estado armazenado...
            SharedPreferences config = context.getSharedPreferences(
                    "QuoteWidget", 0);
            SharedPreferences.Editor edit = config.edit();
            edit.remove(String.format("UpdateRate-%d", widgetId));
            edit.commit();
            System.out.println("Terminou o onDelete");
        }
        super.onDeleted(context, appWidgetIds);
    }
}

* Configure Activity (SettingsActivity.java)

package com.br.mcsoft.quotes.activity;

import com.br.mcsoft.quotes.R;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RadioGroup;

public class SettingsActivity extends Activity implements OnClickListener {
    private int oldTime = 0;
    private int newTime;
    private SharedPreferences config = null;
    private int widgetId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Inicia a excução...
        super.onCreate(savedInstanceState);
        // Chama o layout...
        setContentView(R.layout.activity_settings);

        widgetId = 0;
        // Pega o Id do Widget

        Intent intent = getIntent(); // new Intent(this,
                                        // WidgetProviderSmall.class);
        Bundle extras = intent.getExtras();
        if (extras != null) {
            widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        } else {
            finish();
            return;
        }
        // Seta como "cancelar" preventivamente...
        Intent cancelResultValue = new Intent();
        cancelResultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                widgetId);
        setResult(RESULT_CANCELED, cancelResultValue);

        // Verifica o tempo atualmente setado
        config = this.getSharedPreferences("QuoteWidget", 0);
        try {
            oldTime = config.getInt(String.format("UpdateRate-%d", 
widgetId),
                    -1);
            System.out.println("OldTime: " + oldTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // O Radio Group...
        RadioGroup rg = (RadioGroup) findViewById(R.id.radioTime);
        // Seta o tempo atual no Spinner
        if (oldTime == 5) {
            rg.check(R.id.rbtFiveMin);
        } else if (oldTime == 10) {
            rg.check(R.id.rbtTenMin);
        } else if (oldTime == 15) {
            rg.check(R.id.rbtFifteenMin);
        } else if (oldTime == 20) {
            rg.check(R.id.rbtTwentyMin);
        } else if (oldTime == 30) {
            rg.check(R.id.rbtThirtyMin);
        } else if (oldTime == 60) {
            rg.check(R.id.rbtOneHour);
        } else if (oldTime == 120) {
            rg.check(R.id.rbtTwoHours);
        }

        // Pega e seta os botões...
        Button ok = (Button) findViewById(R.id.btnOk);
        Button cancel = (Button) findViewById(R.id.btnCancel);
        ok.setOnClickListener(this);
        cancel.setOnClickListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // getMenuInflater().inflate(R.menu.activity_settings, menu);
        return true;
    }

    public void onClick(View v) {
        if (v == (Button) findViewById(R.id.btnOk)) {
            // Pega o novo tempo de update...
            RadioGroup rg = (RadioGroup) findViewById(R.id.radioTime);
            int id = rg.getCheckedRadioButtonId();
            if (id == R.id.rbtFiveMin) {
                newTime = 5;
            } else if (id == R.id.rbtTenMin) {
                newTime = 10;
            } else if (id == R.id.rbtFifteenMin) {
                newTime = 15;
            } else if (id == R.id.rbtTwentyMin) {
                newTime = 20;
            } else if (id == R.id.rbtThirtyMin) {
                newTime = 30;
            } else if (id == R.id.rbtOneHour) {
                newTime = 60;
            } else if (id == R.id.rbtTwoHours) {
                newTime = 120;
            }
            if (newTime != oldTime && config != null
                    && widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                System.out.println("newTime: " + newTime);
                Editor configEditor = config.edit();
                configEditor.putInt(String.format("UpdateRate-%d", 
widgetId),
                        newTime);
                configEditor.commit();

                // Envia o RESULT_OK...
                Intent i = new Intent();
                i.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
                setResult(RESULT_OK, i);

                // tell the app widget manager that we're now
                // configured

                // Pega o context
                Context context = getApplicationContext();

                // updateAllWidgets();
                Intent intent = new Intent();
                intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                //intent.setData(Uri.parse("widget_quotes_://widget/id/"
                //      + widgetId));
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
                        new int[] { widgetId });

                PendingIntent newPending = 
PendingIntent.getBroadcast(context,
                        widgetId, intent, 
PendingIntent.FLAG_UPDATE_CURRENT);

                // schedule the new widget for updating

                AlarmManager alarms = (AlarmManager) 
getSystemService(Context.ALARM_SERVICE);
                alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime(), newTime * 1000,
                        newPending);

                System.out.println("Configuração finalizada...");
            }
        }
        finish();
    }
}

Everything else is working fine (it is updating as it should and 
everything, just doesn't show a thing), but, if you want I can update here 
and post more code.

Thanks.

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to