Who (and how) create an instance of AppWidgetProvi

2019-06-14 12:10发布

upd2. The problem has gone after a sort of black magic routine (uninstall, clean Eclipse project, reboot Android device, rebuild, install, run). It is not solved, it has gone. Could anyone please explain what has happened?

upd. Seems, no Java code running at all in my Android widget project modeled after Hello Widget tutorial (ref. comments). Is there any way to run some code to make my widget useful? I believe it is possible because there are a lot of do-something widgets. How they make it?

I modeled a simple Android widget after Hello Widget tutorial: http://nm-blog.sanid.com/2009/07/android-hellowidget-tutorial/

Running it I can see that it's not working at all - the text view is not altered.

Here's some code:

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.pell.hellowidget"
    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" >        
        <receiver android:name="HelloWidgetProvider" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/hello_widget_provider" />
        </receiver>                
    </application>
</manifest>

res/xml/hello_widget_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  android:minWidth="280dp"
  android:minHeight="180dp"
  android:updatePeriodMillis="10000"
  android:initialLayout="@layout/hello_widget_layout"
  android:resizeMode="vertical" />

res/layout/hello_widget_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical|center_horizontal"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>

src/com/pell/hellowidget/HelloWidgetProvider.java:

package com.pell.hellowidget;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.widget.RemoteViews;

public class HelloWidgetProvider extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1,
                1000);

        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    private Date currentTime;

    private class MyTime extends TimerTask {
        RemoteViews remoteViews;
        AppWidgetManager appWidgetManager;
        ComponentName thisWidget;
        DateFormat format = SimpleDateFormat.getTimeInstance(
                SimpleDateFormat.MEDIUM, Locale.getDefault());

        public MyTime(Context context, AppWidgetManager appWidgetManager) {
            this.appWidgetManager = appWidgetManager;
            remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.hello_widget_layout);
            thisWidget = new ComponentName(context, HelloWidgetProvider.class);
        }

        @Override
        public void run() {
            currentTime = new Date();
            remoteViews.setTextViewText(R.id.textView1,
                    format.format(currentTime));
            appWidgetManager.updateAppWidget(thisWidget, remoteViews);
        }
    }
}

As far as I understand it is not working due to nobody instantiates com.pell.hellowidget.HelloWidgetProvider object. What is Java/Android Widget/etc analog for the entry point (int main(int argc, char * argv[]), WinMain, etc)? Who (and how) instantiates AppWidgetProvider object?

1条回答
对你真心纯属浪费
2楼-- · 2019-06-14 12:38

As per your final comment, the . in the android:name can sometimes be essential. As a rule, I always use fully qualified name ("com.super.cool.thing.MySpecialClassActivity") in the manifest because it makes it very clear.

The "entry point" for an AppWidget is the provider class. However, it is only instantiated when it is called and, once onUpdate (or onDestroy) returns, the class is gone. Whilst (I think) you can do what you've done, it wouldn't be considered good practice - generally you should create a defined separate thread from which to manage your widget, either a Service, an AsyncTask, a Thread etc.

Typically, the onUpdate method will create an intent designed to start a Service class which will control the widget. An example of this is in http://www.vogella.com/articles/AndroidWidgets/article.html, section 8 in particular. I would only quibble with one point in that tutorial: it's generally advised to not use updatePeriod. I've also put some considerations for using Services and other things together in Service being re-Created by AlarmManager.

查看更多
登录 后发表回答