0

我试图创建一个小部件,单击时调用配置活动的例程,更新时调用配置活动的另一个例程,更新必须在 30 分钟内,并且创建的所有实例必须单独工作(在 onUpdate 和 onClick 中)。

下面的代码:单击不起作用(看不到 Toast 消息和其他功能)更新对于第一个实例工作正常,但对于多个小部件实例它工作不好:如果我在 10 秒之间创建 2 个实例(并且刷新设置为 20秒)所有将每 10 秒更新一次。

那是我的清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="it.fraschi.controllogiardinowg"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
       android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="it.fraschi.controllogiardinowg.Configurazione"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
            </intent-filter>
        </activity>
        <receiver android:name="it.fraschi.controllogiardinowg.ControlloWidget" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <intent-filter> 
                <action android:name="it.fraschi.controllogiardinowg.ControlloWidget.ACTION_WIDGET_CLICKED"/>
            </intent-filter>
            <intent-filter>
                    <action android:name="it.fraschi.controllogiardinowg.ControlloWidget.MY_OWN_WIDGET_UPDATE" />
                </intent-filter>
            <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider" />
        </receiver>
    </application>
</manifest>

那是我的配置:

package it.fraschi.controllogiardinowg;




import java.util.Calendar;
import java.util.Random;

import android.os.Bundle;
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.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RemoteViews;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

public class Configurazione extends Activity {

private static final String PREFS_NAME  = "it.fraschi.android.ControlloGiardinoWG";

    public static final String NOME  = "nome_";
    private static long millis = 60000;


    private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    private int selectedTextColor;
    private int selectedBackgroundColor;

     public Configurazione() {
            super();
        }

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

            // Set the result to CANCELED.  This will cause the widget host to cancel
            // out of the widget placement if they press the back button.
            setResult(RESULT_CANCELED);

            // Set the view layout resource to use.
            setContentView(R.layout.activity_configurazione);

            // Find the widget id from the intent. 
            Intent intent = getIntent();
            Bundle extras = intent.getExtras();
            if (extras != null) {
                mAppWidgetId = extras.getInt(
                        AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            }

            // If they gave us an intent without the widget id, just bail.
            if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
                finish();
            }



            //final Spinner backgroundColorSelector = (Spinner)findViewById(R.id.backgroundColor);
            final Button    saveButton = (Button)findViewById(R.id.btnSalva);
            final Button    cancelButton = (Button)findViewById(R.id.btnCancel);
            final EditText  editNome = (EditText)findViewById(R.id.editNome);
            /*textColorSelector.setOnItemSelectedListener(new OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                    selectedTextColor = Integer.parseInt(getResources().getStringArray(R.array.textColorsValues)[textColorSelector.getSelectedItemPosition()]);
                }

                @Override
                public void onNothingSelected(AdapterView<?> parentView) {}

            });*/



            saveButton.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    final Context context = Configurazione.this;

                    //prepare Alarm Service to trigger Widget
                       Intent intent = new Intent(ControlloWidget.MY_WIDGET_UPDATE);
                       PendingIntent pendingIntent = PendingIntent.getBroadcast(Configurazione.this, mAppWidgetId, intent, 0);
                       AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
                       Calendar calendar = Calendar.getInstance();
                       calendar.setTimeInMillis(System.currentTimeMillis());
                       calendar.add(Calendar.SECOND, 30);
                       alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), millis, pendingIntent);
                       //ControlloWidget.SaveAlarmManager(alarmManager, pendingIntent);
                    ///


                    SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
                    prefs.putString(NOME + mAppWidgetId, editNome.getText().toString());

                    prefs.commit();

                 // Push widget update to surface with newly set prefix
                    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                    ControlloWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId);

                    // Make sure we pass back the original appWidgetId
                    Intent resultValue = new Intent();
                    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
                    setResult(RESULT_OK, resultValue);
                    finish();
                }
            });

            cancelButton.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    finish();
                }
            });

     }
    /*@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.configurazione, menu);
        return true;
    }*/
     static String getName(Context context, String prefKey ,int appWidgetId) {
            SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
            String valuename = prefs.getString(prefKey + appWidgetId, "Non Trovato");

            return valuename;
        }
     static String getColor(Context context, String prefKey, int appWidgetId){
            ///Test
            SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
            String nome = prefs.getString(prefKey + appWidgetId, "Non Trovato");
            ///
            int number = (new Random().nextInt(100));
            String color = "DaConf"+Integer.toString(number)+nome;
            Toast.makeText(context, "ESEGUITO", Toast.LENGTH_LONG).show();
            return color;
     }


}

那是我的小部件:

        import java.text.DateFormat;
        import java.text.SimpleDateFormat;
        import java.util.Date;
        import java.util.Random;

        import android.app.AlarmManager;
        import android.app.PendingIntent;
        import android.appwidget.AppWidgetManager;
        import android.appwidget.AppWidgetProvider;
        import android.content.ComponentName;
        import android.content.Context;
        import android.content.Intent;
        import android.os.Bundle;
        import android.os.Environment;
        import android.os.StatFs;

        import android.widget.RemoteViews;
        import android.widget.Toast;

        public class ControlloWidget extends AppWidgetProvider {
            public static String ACTION_WIDGET_CLICKED = "it.fraschi.controllogiardinowg.ESEGUI";
            public static String MY_WIDGET_UPDATE = "it.fraschi.controllogiardinowg.ControlloWidget.MY_OWN_WIDGET_UPDATE";
            static String strWidgetText = "";
            public static Boolean choice = false;


                @Override

                public void onReceive(Context context, Intent intent) {
                    // TODO Auto-generated method stub
                    //super.onReceive(context, intent);
                    String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date()); 
                    if(MY_WIDGET_UPDATE.equals(intent.getAction())){
                        Bundle extras = intent.getExtras();
                           if(extras!=null) {
                            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                            ComponentName thisAppWidget = new ComponentName(context.getPackageName(),
    ControlloWidget.class.getName());
                            int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
                            choice=false;
                            onUpdate(context, appWidgetManager, appWidgetIds);
                           }
                        Toast.makeText(context, "WIDGET UPDATE" +currentDateTimeString, Toast.LENGTH_LONG).show();
                    }
                    //Test Click
                    if(ACTION_WIDGET_CLICKED.equals(intent.getAction())){
                        Bundle extras = intent.getExtras();
                           if(extras!=null) {
                            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                            ComponentName thisAppWidget = new ComponentName(context.getPackageName(),
    ControlloWidget.class.getName());
                            int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
                            choice=true;
                            onUpdate(context, appWidgetManager, appWidgetIds);
                           }
                        Toast.makeText(context, "WIDGET PREMUTO", Toast.LENGTH_LONG).show();
                    }
                    //TestClick
                }

                @Override
                public void onEnabled(Context context) {
                    // TODO Auto-generated method stub
                    //super.onEnabled(context);

                    Toast.makeText(context, "onEnabled()", Toast.LENGTH_LONG).show();
                }

                @Override
                public void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {
                    // TODO Auto-generated method stub
                    //super.onUpdate(context, appWidgetManager, appWidgetIds);

                    final int N = appWidgetIds.length;
                    for (int i=0; i<N; i++) {
                        int appWidgetId = appWidgetIds[i];
                        // Create an Intent to launch ExampleActivity
                        Intent intent = new Intent(context, ControlloWidget.class);
                        intent.setAction(ACTION_WIDGET_CLICKED);
                        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, intent,
                                PendingIntent.FLAG_UPDATE_CURRENT);

                        // Get the layout for the App Widget and attach an on-click listener
                        // to the button
                        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
                        views.setOnClickPendingIntent(R.id.btnEsegui, pendingIntent);
                        // Tell the AppWidgetManager to perform an update on the current app widget
                        appWidgetManager.updateAppWidget(appWidgetId, views);
                        //updateAppWidget(context, appWidgetManager, appWidgetId);

                        //Toast.makeText(context, "onUpdate(): " + String.valueOf(i) + " : " +  String.valueOf(appWidgetId), Toast.LENGTH_LONG).show();
                    }
                     RemoteViews remoteWidget = new RemoteViews(context.getPackageName(),R.layout.widget);


                }



                public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,int appWidgetId){
                        //TestOnClick
                       RemoteViews remoteWidget = new RemoteViews(context.getPackageName(),R.layout.widget);
                       ///
                       Intent esegui = new Intent(context, ControlloWidget.class);
                       esegui.setAction(ACTION_WIDGET_CLICKED);
                       //Intent esegui = new Intent(ControlloWidget.ACTION_WIDGET_CLICKED);
                       PendingIntent pendingEsegui = PendingIntent.getBroadcast(context, appWidgetId, esegui, 0);
                       remoteWidget.setOnClickPendingIntent(R.id.btnEsegui, pendingEsegui);
                    //

                        //
                        if (choice){
                            RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
                            updateViews.setTextViewText(R.id.btnEsegui, "[" + String.valueOf(appWidgetId) + "]" + strWidgetText +
    Configurazione.getColor(context, Configurazione.NOME, appWidgetId));
                            appWidgetManager.updateAppWidget(appWidgetId, updateViews);

                            Toast.makeText(context, "onClick(): " + String.valueOf(appWidgetId) + "\n" + strWidgetText,
    Toast.LENGTH_LONG).show();

                        }else{
                                int number = (new Random().nextInt(100));
                                strWidgetText = Integer.toString(number);

                                RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
                                updateViews.setTextViewText(R.id.btnEsegui, "[" + String.valueOf(appWidgetId) + "]" + strWidgetText +
    Configurazione.getName(context, Configurazione.NOME, appWidgetId));
                                appWidgetManager.updateAppWidget(appWidgetId, updateViews);

                                Toast.makeText(context, "updateAppWidget(): " + String.valueOf(appWidgetId) + "\n" + strWidgetText,
    Toast.LENGTH_LONG).show();
                            }
                }
                static AlarmManager myAlarmManager;
                static PendingIntent myPendingIntent;


                @Override
                public void onDeleted(Context context, int[] appWidgetIds) {
                    // TODO Auto-generated method stub
                    //super.onDeleted(context, appWidgetIds);
                    myAlarmManager.cancel(myPendingIntent);
                    Toast.makeText(context, "onDeleted()", Toast.LENGTH_LONG).show();
                }
                static void SaveAlarmManager(AlarmManager tAlarmManager, PendingIntent tPendingIntent){
                    myAlarmManager = tAlarmManager;
                    myPendingIntent = tPendingIntent;
                }
        }

*

4

1 回答 1

1

For Timing under 30 mins and multiple instances i've decided to use only one timer for all instances.

Below the code onCreate of Configuration Class:

private static long millis = 20000;

SharedPreferences read = context.getSharedPreferences(PREFS_NAME, 0);
String firstinstance = read.getString("FirstInstance", "KO");
if (firstinstance.equals("KO")) {
    SharedPreferences.Editor write = context.getSharedPreferences(
            PREFS_NAME, 0).edit();
    write.putString("FirstInstance", "OK");
    write.commit();
    Intent intent = new Intent(ControlloWidget.MY_WIDGET_UPDATE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            Configurazione.this, 0, intent, 0);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.SECOND, 10);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
            calendar.getTimeInMillis(), millis, pendingIntent);
    ControlloWidget.SaveAlarmManager(alarmManager, pendingIntent);
}

revert that process onDisabled of WidgetClass:

@Override
public void onDisabled(Context context) {
    // TODO Auto-generated method stub
    //super.onDisabled(context);
    SharedPreferences.Editor write = context.getSharedPreferences(PREFS_NAME, 0).edit();    
    write.putString("FirstInstance", "KO" );    
    write.commit();
    myAlarmManager.cancel(myPendingIntent);
}
static void SaveAlarmManager(AlarmManager tAlarmManager, PendingIntent tPendingIntent){
    myAlarmManager = tAlarmManager;
    myPendingIntent = tPendingIntent;
}

Now, setting up button Action and My Own Update: Class declaration:

public static String ACTION_WIDGET_CLICKED = "your.packagename.ACTION_WIDGET_CLICKED";
public static String MY_WIDGET_UPDATE = "your.packagename.MY_WIDGET_UPDATE";

onReceive method:

@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    super.onReceive(context, intent);
    choice = false;
    // ////Toast.makeText(context, intent.getAction(),
    // ////Toast.LENGTH_LONG).show();
    // choice=false;

    Bundle extras = intent.getExtras();

    if (MY_WIDGET_UPDATE.equals(intent.getAction())) {
        choice = false;

        AppWidgetManager appWidgetManager = AppWidgetManager
                .getInstance(context);
        ComponentName thisAppWidget = new ComponentName(
                context.getPackageName(), ControlloWidget.class.getName());
        int[] appWidgetIds = appWidgetManager
                .getAppWidgetIds(thisAppWidget);

        onUpdate(context, appWidgetManager, appWidgetIds);
        // ////Toast.makeText(context, "AUTOUPDATE",
        // ////Toast.LENGTH_LONG).show();
    } else

    if (ACTION_WIDGET_CLICKED.equals(intent.getAction())) {
        // choice =true;
        AppWidgetManager appWidgetManager = AppWidgetManager
                .getInstance(context);
        ComponentName thisAppWidget = new ComponentName(
                context.getPackageName(), ControlloWidget.class.getName());
        int[] appWidgetIds = appWidgetManager
                .getAppWidgetIds(thisAppWidget);
        int appWidgetId = intent.getIntExtra(
                AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
        // ////////
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget);
        remoteViews.setTextViewText(R.id.btnEsegui,
                Configurazione.getName(context, "nome", appWidgetId));

        // ACTION CODE HERE
        appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
        Log.d("LOG_Esecuzione",
                "Log Esecuzione, Widget n." + String.valueOf(appWidgetId));

    }

}

Then onUpdate and updateAppWidget Method:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    // TODO Auto-generated method stub
    // super.onUpdate(context, appWidgetManager, appWidgetIds);
    final int N = appWidgetIds.length;
    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,int appWidgetId){
    //TestOnClick

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
    Intent myIntent = new Intent(context, ControlloWidget.class);
    myIntent.setAction(ACTION_WIDGET_CLICKED);
    myIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context,appWidgetId,
            myIntent, 0);
    remoteViews.setOnClickPendingIntent(R.id.btnEsegui, pendingIntent);
    remoteViews.setTextViewText(R.id.btnEsegui,Configurazione.getName(context, "nome", appWidgetId));
    //On Update Code, Requested Action when onUpdate is called (for all widget), it also refresh pending intent                     

    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
    Log.d("LOG_UPDATE", "Log Update, Widget n."+String.valueOf(appWidgetId));
                                }
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}

For separate instances is necessary:

On intentcreation:(on updateAppWidget)

RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
Intent myIntent = new Intent(context, ControlloWidget.class);
myIntent.setAction(ACTION_WIDGET_CLICKED);
            //The line below is the appWidgetId Specification
myIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,appWidgetId,
        myIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.btnEsegui, pendingIntent);

On receiving broadcast: (on onReceive)

if (ACTION_WIDGET_CLICKED.equals(intent.getAction())){
    //Commented are not used on that example
    //AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    //ComponentName thisAppWidget = new ComponentName(context.getPackageName(), ControlloWidget.class.getName());
    //int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
    int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

now we could call any routine everywhere passing appWidgetId and Context to function... Example:

Action.SomeAction(context,appWidgetId);

For UPDATE TIMER, is also possible (without using preferences): Like the other intent could use putExtra then on broadcast: retrieve the int on broadcast receive

int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

BUT now we don't call onUpdate method but directly updateAppWidget with that alternative solution every widget has his own time refresh (maybe configurable) I've preferred to have only one timer process active at same time and get all the widget updated at first instance widget update time

于 2013-04-05T19:07:10.317 回答