简体   繁体   English

单击窗口小部件时配置活动不起作用

[英]Configuration activity not working when widget is clicked

I have been trying to figure out this problem for ages and tried at least 10 solutions on stack overflow with no success. 我一直试图找出这个问题,并且尝试了至少10个解决方案,但没有成功。

I have created a Widget class that display some numbers on the home screen which updates every 5 minutes. 我创建了一个Widget类,该类在主屏幕上显示一些数字,每5分钟更新一次。 The Widget is a button, which when the user clicks on it, the configuration activity is loaded up so the widget can be updated. 窗口小部件是一个按钮,当用户单击它时,会加载配置活动,以便可以更新窗口小部件。

When I create the widget the first time, the configuration activity opens and users can type in the text box. 首次创建窗口小部件时,配置活动将打开,用户可以在文本框中键入内容。 Once the configuration is done, the widget is updated - all working as intended. 配置完成后,将更新小部件-所有部件均按预期工作。 However when the button is pressed the configuration activity does not launch again. 但是,当按下按钮时,配置活动不会再次启动。 The weird thing is that when I re run the app via android studio or reboot the phone, the activity can be launched. 奇怪的是,当我通过android studio重新运行该应用程序或重新启动手机时,可以启动该活动。 I think it has to do with it not updating the button pressing for some reason, but I cannot find where to fix it. 我认为这与由于某种原因而不更新按钮的按下按钮有关,但是我找不到修复它的位置。

I have seen a couple of similar questions that have my issue and tried their solutions but it does not work at all. 我看到了几个类似的问题遇到了我的问题,并尝试了他们的解决方案,但这根本不起作用。 I am pretty new at android programming so I might have overlooked something. 我是android编程的新手,所以我可能忽略了一些东西。 I have hard coded some variable pretty badly which needed to be changed but I don't think that would affect the launching of the activity. 我对某些变量进行了严格的硬编码,需要对其进行更改,但是我认为这不会影响活动的启动。

Here is my WidgetProvider, Configuration Activity classes and the manifest. 这是我的WidgetProvider,配置活动类和清单。

LPWidget.java LPWidget.java

public class LPWidget extends AppWidgetProvider {
private static final String LOG_TAG = "ExampleWidget";
static int nowLP = LPWidgetConfigureActivity.currentLP ;
static int maxNowLP = LPWidgetConfigureActivity.maxLP;
static boolean notfirstTime = false;


/**
 * Custom Intent name that is used by the AlarmManager to tell us to update the clock once per second.
 */
public static String CLOCK_WIDGET_UPDATE = "doingitnow.simplelptracker.CLOCK_WIDGET_UPDATE";

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);

    if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
        Log.d(LOG_TAG, "Clock update");
        // Get the widget manager and ids for this widget provider, then call the shared
        // clock update method.
        ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
        for (int appWidgetID: ids) {
            updateAppWidget(context, appWidgetManager, appWidgetID);

        }
    }
}

private PendingIntent createClockTickIntent(Context context) {
    Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    return pendingIntent;
}

@Override
public void onDisabled(Context context) {
    super.onDisabled(context);
    Log.d(LOG_TAG, "Widget Provider disabled. Turning off timer");
    AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(createClockTickIntent(context));
}

@Override
public void onEnabled(Context context) {
    super.onEnabled(context);
    Log.d(LOG_TAG, "Widget Provider enabled.  Starting timer to update widget every second");
    AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.SECOND, 10);
    alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 10000, createClockTickIntent(context));
}


@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    final int N = appWidgetIds.length;

    Log.d(LOG_TAG, "Updating Example Widgets.");

    // Perform this loop procedure for each App Widget that belongs to this
    // provider
    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.lpwidget);
        Intent configIntent = new Intent(context, LPWidgetConfigureActivity.class);
        configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        configIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        configIntent.setData(Uri.parse(configIntent.toUri(Intent.URI_INTENT_SCHEME)));
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.button, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);


        // Update The clock label using a shared method
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
    if (notfirstTime) { //if it is not the first time, update
        if (nowLP < maxNowLP) { //if the nowLP less than the max, add one.
            nowLP = nowLP + 1;

        }
    }
    notfirstTime = true;

    String StringNowLP = "LP: " + Integer.toString(nowLP) + "/" + Integer.toString(maxNowLP);

    RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.lpwidget);
    updateViews.setTextViewText(R.id.button, StringNowLP);
    appWidgetManager.updateAppWidget(appWidgetId, updateViews);
}

LPWidgetConfigureActivity.java LPWidgetConfigureActivity.java

public class LPWidgetConfigureActivity extends Activity {

static int currentLP = 20;
static int maxLP = 50;

int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;


public LPWidgetConfigureActivity() {
    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 the user presses the back button.
    setResult(RESULT_CANCELED);

    setContentView(R.layout.lpwidget_configure);


    // 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 this activity was started with an intent without an app widget ID, finish with an error.
    if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
        finish();
    }
    final EditText currentLPText = (EditText) findViewById(R.id.currentLPText);
    final EditText MaxLPText = (EditText) findViewById(R.id.MaxLPText);
    Button applyButton = (Button) findViewById(R.id.add_button);
    applyButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final Context context = LPWidgetConfigureActivity.this;
            try { //No empty text - update all
                String intcurrentLP = currentLPText.getText().toString();
                String intMaxLP = MaxLPText.getText().toString();
                currentLP = Integer.parseInt(intcurrentLP);
                maxLP = Integer.parseInt(intMaxLP);
                LPWidget.nowLP = currentLP;
                LPWidget.maxNowLP = maxLP;

            } catch (NumberFormatException e) {
                try { //Empty currentLP text - update MaxLP
                    String intMaxLP = MaxLPText.getText().toString();
                    maxLP = Integer.parseInt(intMaxLP);
                    LPWidget.maxNowLP = maxLP;
                    Context toastcontext = getApplicationContext();
                    CharSequence text = "Max LP is updated only";
                    int duration = Toast.LENGTH_LONG;

                    Toast toast = Toast.makeText(toastcontext, text, duration);
                    toast.show();
                } catch (NumberFormatException e1) {
                    try { //empty MaxLP text - update currentLP
                        String intcurrentLP = currentLPText.getText().toString();
                        currentLP = Integer.parseInt(intcurrentLP);
                        LPWidget.nowLP = currentLP;
                        Context toastcontext = getApplicationContext();
                        CharSequence text = "Current LP is updated only";
                        int duration = Toast.LENGTH_LONG;

                        Toast toast = Toast.makeText(toastcontext, text, duration);
                        toast.show();
                    } catch (NumberFormatException e2) { //All empty text - No changes
                        Context toastcontext = getApplicationContext();
                        CharSequence text = "No Text Inputted - No Changes done";
                        int duration = Toast.LENGTH_LONG;

                        Toast toast = Toast.makeText(toastcontext, text, duration);
                        toast.show();

                    }
                }
            }

            LPWidget.notfirstTime = false;

            // It is the responsibility of the configuration activity to update the app widget
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            LPWidget.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();
        }
    });
}

AndroidManifest.xml AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="doingitnow.simplelptracker" >

<application
    android:allowBackup="true"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.WallpaperSettings" >

    <activity
        android:name=".LPMainPage"
        android:label="@string/title_activity_lpmain_page"
        android:theme="@android:style/Theme.WallpaperSettings" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name=".LPWidgetConfigureActivity"
        android:theme="@android:style/Theme.WallpaperSettings" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
        </intent-filter>
    </activity>

    <receiver android:name=".LPWidget" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="doingitnow.simplelptracker.CLOCK_WIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/lpwidget_info" />
    </receiver>

    <activity
        android:name=".LPUpdateActivity"
        android:label="@string/title_activity_lpupdate"
        android:theme="@android:style/Theme.WallpaperSettings">
        <intent-filter>

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>


</application>

After much pain, I managed to figure out why the config activity never ran. 经过一番痛苦之后,我设法弄清了为什么配置活动从未运行过。

Firstly, the calendar.add(Calendar.SECOND, 10); 首先, calendar.add(Calendar.SECOND, 10); means that once the alarm was set, it waited 10 seconds until the alarm was fired. 表示一旦设置了警报,它将等待10秒钟,直到触发警报为止。 This means if I were to finish my config activity before 10 seconds, It would not fire the alarm and the update until 10 seconds was up. 这意味着,如果我要在10秒钟之前完成配置活动,它将在10秒钟结束之前不会触发警报和更新。 If the activity was done 10 seconds after alarm, the activity would work as normal. 如果在警报后10秒钟完成了该活动,则该活动将正常运行。

However when the config activity was updating the widget LPWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId); 但是,当配置活动正在更新小部件LPWidget.updateAppWidget(context, appWidgetManager, mAppWidgetId); would only update what was on screen and not create the remote view for the button, since it was in the onUpdate() function. 因为它在onUpdate()函数中,所以只会更新屏幕上的内容,而不会为按钮创建远程视图。 Since that function would never update since I set the updateperiodmillis in the info provider to 0, the remote view would be launched after the alarm update. 由于自从我将信息提供程序中的updateperiodmillis设置为0以来,该函数永远不会更新,因此在警报更新后将启动远程视图。 Furthermore, two Remote Views were made, which cause more confusion, so merging the two Remote Views I had and place it in the updateAppWidget(context, appWidgetManager, mAppWidgetId); 此外,制作了两个远程视图,这引起了更多的混乱,因此将我拥有的两个远程视图合并,并将其放置在updateAppWidget(context, appWidgetManager, mAppWidgetId); would mean the the button can be pressed and the widget is updated on screen. 表示可以按下按钮,并且在屏幕上更新小部件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM