1. Nimm jetzt an unserem Uhans - 3. ADVENT - Gewinnspiel teil - Alle Informationen findest Du hier!

Widget mit Config

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von egon232, 29.11.2010.

  1. egon232, 29.11.2010 #1
    egon232

    egon232 Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    91
    Erhaltene Danke:
    1
    Registriert seit:
    05.02.2010
    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
     
  2. ko5tik, 29.11.2010 #2
    ko5tik

    ko5tik Android-Experte

    Beiträge:
    620
    Erhaltene Danke:
    40
    Registriert seit:
    14.10.2009
    Phone:
    HTC Hero
    Was spricht dagegen, den Widget-ID als name für deine sharedPreferences zu nehmen anstatt "prefs"?
     
  3. egon232, 29.11.2010 #3
    egon232

    egon232 Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    91
    Erhaltene Danke:
    1
    Registriert seit:
    05.02.2010
    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: 29.11.2010
  4. ko5tik, 29.11.2010 #4
    ko5tik

    ko5tik Android-Experte

    Beiträge:
    620
    Erhaltene Danke:
    40
    Registriert seit:
    14.10.2009
    Phone:
    HTC Hero
    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
     
  5. egon232, 29.11.2010 #5
    egon232

    egon232 Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    91
    Erhaltene Danke:
    1
    Registriert seit:
    05.02.2010
    Aber macht es nicht relativ wenig sinn, den Batterystatus alle 15-30 min zu aktualisieren. Man will ja immer den aktuellen Status haben.
     
  6. ko5tik, 29.11.2010 #6
    ko5tik

    ko5tik Android-Experte

    Beiträge:
    620
    Erhaltene Danke:
    40
    Registriert seit:
    14.10.2009
    Phone:
    HTC Hero
    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
     
  7. egon232, 29.11.2010 #7
    egon232

    egon232 Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    91
    Erhaltene Danke:
    1
    Registriert seit:
    05.02.2010
    Genau aus diesem Grund wollte ichs ja mit einem Service und nem BroadcastReceiver machen, der auf BATTERY_CHANGED wartet..

    Aktuell sind es 10 Stufen:

    [​IMG]
     
  8. egon232, 29.11.2010 #8
    egon232

    egon232 Threadstarter Android-Hilfe.de Mitglied

    Beiträge:
    91
    Erhaltene Danke:
    1
    Registriert seit:
    05.02.2010
    Hat noch jemand eine Idee wie ich das mittels eines Services machen kann?
     
  9. ko5tik, 29.11.2010 #9
    ko5tik

    ko5tik Android-Experte

    Beiträge:
    620
    Erhaltene Danke:
    40
    Registriert seit:
    14.10.2009
    Phone:
    HTC Hero
    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
     
  10. tenji73, 17.03.2011 #10
    tenji73

    tenji73 Neuer Benutzer

    Beiträge:
    5
    Erhaltene Danke:
    1
    Registriert seit:
    13.12.2010
    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: 17.03.2011

Diese Seite empfehlen