Widget mit Config

E

egon232

Ambitioniertes Mitglied
1
Hallo,

Habe ein kleines Problem. Ich versuche mich gerade an einem Batterie-Widget, welches mit einem Service im Hintergrund den Status aktualisiert. Das funktioniert auch soweit. Nun möchte ich, dass man beim hinzufügen auf dem Homescreen zuerst eine Config-Activity sieht:

Manifest:
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.swob.battery" android:versionCode="1" android:versionName="1.0">
    <application android:label="@string/app_name" android:icon="@drawable/battery_100">
        <!-- Broadcast Receiver that will process AppWidget updates -->
        <service android:name=".batteryService"></service>
        <receiver android:name=".BatteryWidget" 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/widget_provider" />
        </receiver>
        <receiver android:name=".BootReceiver"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>
        <activity android:name=".BatteryConfig"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
</manifest>
AppWidgetProvider:
Code:
package de.swob.battery;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class BatteryWidget extends AppWidgetProvider {
    
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        Log.v("Test", "Starte Service");
        Intent service = new Intent(context, batteryService.class);
        context.startService(service);
    }
    
    public void onDisabled(Context context) {
        // TODO Auto-generated method stub
        Log.v("Test", "Stoppe Service");
        context.stopService(new Intent(context, batteryService.class));
    }

}
Config-Activity:
Code:
package de.swob.battery;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

public class BatteryConfig extends Activity {
    private Context self = this;
    private int appWidgetId;
    private Spinner spinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v("Test", "Starte Config");
        // hole WidgetID
        Intent launchIntent = getIntent();
        Bundle extras = launchIntent.getExtras();
        appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);

        // setzte CancelValue
        Intent cancelResultValue = new Intent();
        cancelResultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                appWidgetId);
        setResult(RESULT_CANCELED, cancelResultValue);
        
        // Lade Config-UI
        setContentView(R.layout.config);
        spinner = (Spinner) findViewById(R.id.spColor);
        
        // fülle Spinner
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.colors, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        
        // OK button
        Button ok = (Button) findViewById(R.id.ok);
        
        // setzte OnClick-Listener
        ok.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                
                // hole Spinner-Value
                String value = spinner.getSelectedItem().toString();

                // Speichere Auswahl
                SharedPreferences prefs = self.getSharedPreferences("prefs", 0);
                SharedPreferences.Editor edit = prefs.edit();
                edit.putString("color_" + appWidgetId, value);
                edit.commit();

                // setze ResultValue
                Intent resultValue = new Intent();
                resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                setResult(RESULT_OK, resultValue);
                finish();
            }
        });

        // cancel button
        Button cancel = (Button) findViewById(R.id.cancel);
        cancel.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                finish();
            }
        });
    }
}
Service:
Code:
package de.swob.battery;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;

public class batteryService extends Service {
    private int currentBatteryLevel = 0;
    private RemoteViews updateViews;
    private ComponentName thisWidget;
    private AppWidgetManager manager;

    private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            currentBatteryLevel = intent.getIntExtra("level", 0);
            updateViews.setTextViewText(R.id.widgetText, String
                    .valueOf(currentBatteryLevel));
            setBGGraphic();
            manager.updateAppWidget(thisWidget, updateViews);
        }
    };

    @Override
    public void onStart(Intent intent, int startId) {
        Log.v("Test", "Service started");
        // registriere BroadcastReceiver
        registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        updateViews = new RemoteViews(getPackageName(), R.layout.main);
        updateViews.setTextViewText(R.id.widgetText, String
                .valueOf(currentBatteryLevel));
        setBGGraphic();
        thisWidget = new ComponentName(this, BatteryWidget.class);
        manager = AppWidgetManager.getInstance(this);
        manager.updateAppWidget(thisWidget, updateViews);
    }

    private void setBGGraphic() {
           //code
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

}
Widget.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:maxWidth="80dip" 
    android:maxHeight="100dip" android:initialLayout="@layout/main" 
    android:configure="de.swob.battery.BatteryConfig"/>
Mein Problem ist jetzt, wie bekomme ich im Service die Prefs zu der widgetId?

Grüße
Fabi
 
egon232 schrieb:
Mein Problem ist jetzt, wie bekomme ich im Service die Prefs zu der widgetId?

Was spricht dagegen, den Widget-ID als name für deine sharedPreferences zu nehmen anstatt "prefs"?
 
Hi,

erstmal danke für deine antwort. Des ist ja nicht das Problem.
Ich weis nur nicht, wie ich an die widgetID komme, für die ich gerade die Einstellung vorgenommen habe.

Edit:
Was mich auch noch wundert ist, sollte sich der Service nicht erst starten, wenn ich die Config activity verlassen habe?
 
Zuletzt bearbeitet:
Von lauter copypasting hast du übersehen, das du den Widget-ID bereits aus dem Intent rausgeholt hast ;)

Also - auf keine fall den Service starten - dafür sind die Widget nicht gedacht. Maximal eine Update-Schedulen ( für Batteriestatus würde ich eher 15 Minuten, oder sogar 30 Minuten unscharf vorschlagen )


Nach dem die Konfiguration beendet wurde, werden deine callbacks aufgerufen
( onUpdate() aber nicht ) - schau mal genau in der Doku nach
 
Aber macht es nicht relativ wenig sinn, den Batterystatus alle 15-30 min zu aktualisieren. Man will ja immer den aktuellen Status haben.
 
Wenn du die Update-Frequenz unter 1 MInute setzt, wird man deinen Batteriebalken zuschauen können ;) Vieviele Anzeige-Stufen planst du überhaupt? 5? 10? Dan sind 15 Minuten mehr als ausreichend
 
Genau aus diesem Grund wollte ichs ja mit einem Service und nem BroadcastReceiver machen, der auf BATTERY_CHANGED wartet..

Aktuell sind es 10 Stufen:

devices.png
 
Hat noch jemand eine Idee wie ich das mittels eines Services machen kann?
 
OK, dann hast du deinen BroadcasReceiver, der BatteryChanged empfängt
( und dieser Intent hat natürlich kein Widget ID )

Dann kannst du entweder
- einfach alle Widgets von deinen Typ updaten
Code:
    AppWidgetManager manager = AppWidgetManager.getInstance(context);
            final int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, this.getClass()));

- Wert irgendwo in den Preferences speichern und auf Update-Even warten

Wenn keine extra-Konfiguration für den WIdget gibt, würde ich die 1. Möglichkeit wählen
 
habe mein widget genauso mit service extender & BroadcastReceiver gemacht... funktioniert alles soweit super ausser:
- die funktion draw() wird aufgerufen (das Log.v ausgegeben) das updateAppWidget() aber nicht immer - es ist nicht nachvollziebar und nicht reproduzierbar... so wird mein widget nicht immer neugezeichnet...
es bleibt auch nach dem booten mal schwarz & mal ist es korrekt...

Code:
<pseudocode>
public class bla extends Service {

void draw(Context)
{
    Log.v("draw","aufgerufen");
    //code code code...
    // create some bitmaps 
    appWidgetManager.updateAppWidget( thisWidget, remoteViews);
}
}     
</pseudocode>
vielleicht hat jemand eine idee?
danke & gruss
tom

p.s. übrigens - die widget id übergebe ich an den service mit dem holzhammer: ;-)
Code:
service.putExtra("widgetId", widgetId);
 
Zuletzt bearbeitet:

Ähnliche Themen

wernho
Antworten
11
Aufrufe
678
wernho
wernho
B
Antworten
4
Aufrufe
470
bb321
B
FabianDev
Antworten
5
Aufrufe
548
swa00
swa00
Zurück
Oben Unten