Countdown-Service für Activity und Widget

M

MrJack

Ambitioniertes Mitglied
10
Hallo!

Ich möchte folgendes implementieren:
1) Ein Service, welches einen Countdown startet
2) Eine Activity, die jede Sekunde (mittels BroadcastReceiver? die aktuelle Zeit bekommt und ins UI einträgt)
3) Ein Widget, welches jede Minute die aktuelle Zeit bekommt und ins UI einträgt

Leider weiß ich nicht genau, wie das umzusetzen ist.
Folgendes habe ich schon:

Service:
Code:
public class MyService extends Service
{
    public static final String BROADCAST_ACTION = "myaction";

    @Override
    public void onCreate()
    {
        final Intent intent = new Intent( BROADCAST_ACTION );
        
        new CountDownTimer( 100000, 1000 )
        {
            @Override
            public void onTick( long millisUntilFinished )
            {
                // Zeit entsprechend berechnen und in bestimmtes Format bringen (z.B. HH:mm:SS)
                
                intent.putExtra( "time", formattedString );
                sendBroadcast( intent );
            }
            
            @Override
            public void onFinish()
            {
            }
        }.start();
    }

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

Hier ist meine Activity:
Code:
public class MyActivity extends Activity
{
    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive( Context context, Intent intent )
        {
            String time = intent.getStringExtra( "time" );
            TextView tvTime= (TextView) findViewById( R.id.tvTime);
            tvTime.setText( time  );
        }
    };

    @Override
    public void onCreate( Bundle savedInstanceState )
    {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.main );
        
        intent = new Intent( this, MyService.class );
        startService( intent );
        registerReceiver( broadcastReceiver, new IntentFilter( MyService.BROADCAST_ACTION ) );
    }
}

Bis hierhin funktioniert alles wunderbar.
Problem ist jetzt: Wie erstelle ich das Widget, welches minütlich die Informationen vom Service bekommt?

Zunächst brauche ich ja sowieso mal irgendein Workaround mittels AlarmManager, damit ich die Aktualisierungszeit auf 1 Minute verringen kann.
Wie soll ich das umsetzen?

Danke
 
Also, hab mir das mal angesehen, hilft mir leider noch nicht ganz weiter.
In diesen Beispielen wird nämlich das Widget direkt vom Service upgedatet.

Ich habe aber vor, dass ich mich im Widget ans Service hänge und im Widget dann update, wenn das Service mir das sagt.

Also eine Art Listener. Geht das nicht mit einem BroadcastReceiver?

Ich will nämlich meine Funktionalität im Service halten -> dort wird der Countdown gestartet und jede Sekunde ein Broadcast gesendet.

Und dann will ich in einer Activity UND einem Widget auf diesen Broadcast reagieren und erst in den entsprechenden Klassen das UI updaten.
 
Hallo Du kannst im Service an der Stelle an der du den Countdown Broadcast verschickst das Widget direkt updaten. Was meinst du mit "im Widget ans Service hängen" ?
 
strider schrieb:
Hallo Du kannst im Service an der Stelle an der du den Countdown Broadcast verschickst das Widget direkt updaten. Was meinst du mit "im Widget ans Service hängen" ?

Danke für die Antwort.
Es geht mir um folgendes Prinzip: Ich habe ein Service und verschiedene Activities bzw. Widgets (können ja mehrere sein), die sich an diesem Service "registieren" sollen. Wenn das Service dann jede Sekunde einen Broadcast ausschickt, sollten alle registrierten Activities / Widgets die Nachricht bekommen und entsprechend weiterbehandeln (d.h. ins UI eintragen). Einziger Unterschied sollte eben sein, dass die Activity jede Sekunde aktualisiert wird und das Widget jede Minute.

Ich will das ganze so konzipieren, dass das Service nichts über die Activity oder das Widget weiß, sondern einfach nur den Broadcast aussendet.
In den genannten Beispielen greife ich vom Service immer aufs Widget zu und update dieses. Was ist aber, wenn ich mehrere Widgets habe, die auf das Service reagieren sollen? Muss ich dann alle Widgets direkt im Service updaten?

Wie ist hier die korrekte Vorgehensweise?
 
Das Widget muss von aussen aktualisiert werden was meistens über einen Service geschieht oder über den AppWidgetProvider(ein getuneter BroadcastReceiver). Es hat leider eigenen code der sich and aktiv bei einem Service registrieren kann. Es wäre also vorteilhaft, wenn sowieso schon ein Service da ist der Broadcasts verschickt das Update gleich an der Stelle passieren zu lassen an dem der Broadcast verschickt wird in dem Service.
Das erspart eine Menge Overhead.
Wenn du die Widgets komplett abkoppeln willst um später z.B weitere Widgets nachzuliefern ohne das Projekt mit dem Service neu zu kompilieren, dann must du einen BroadcastReceiver erstellen diesem weist du im XML Manifest über einen Intent Filter das zu auf was er lauschen soll, der Receiver wiederum startet einen Service und der Service aktualisiert das Widget. Das Update des Widgets direkt im Broadcast Receiver ist nicht ratsam da der BroadcastReceiver nur für ein paar Milisekunden laufen darf. Wenn du die Widgets aber immer zusammen mit dem kompletten Projekt auslieferst und nicht getrennt davon, dann wäre das meiner Meinung nach eine unnötige verkomplizierung.
 
  • Danke
Reaktionen: MrJack
Ok, danke nochmals, habs jetzt folgendermaßen gelöst:

Service:
Code:
public class MyService extends Service
{
    public static final String BROADCAST_ACTION = "myaction";

    @Override
    public void onCreate()
    {
        final Intent intent = new Intent( BROADCAST_ACTION );
        
        new CountDownTimer( 100000, 1000 )
        {
            @Override
            public void onTick( long millisUntilFinished )
            {
                // Zeit entsprechend berechnen und in bestimmtes Format bringen (z.B. HH:mm:SS)
                
                intent.putExtra( "time", formattedString );
                sendBroadcast( intent );

                [B]updateWidgets( formattedString );[/B]
            }
            
            @Override
            public void onFinish()
            {
            }
        }.start();
    }

    @Override
    public IBinder onBind( Intent intent )
    {
        // TODO Auto-generated method stub
        return null;
    }
[B]
    private void updateWidgets( String time )
    {
        AppWidgetManager appmanager = AppWidgetManager.getInstance( this );
        ComponentName cmpName = new ComponentName( this, MyWidget.class );
        int[] widgetIds = appmanager.getAppWidgetIds( cmpName );
        
        for ( int wid : widgetIds )
        {
            RemoteViews rView = new RemoteViews( getPackageName(), R.layout.widget_layout_4_1 );
            rView.setTextViewText( R.id.time, time );
            
            appmanager.updateAppWidget( wid, rView );
        }
    }
}
[/B]
BroadcastReceiver:
Code:
public class MyReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive( Context context, Intent intent )
    {
        context.startService( new Intent( context, MyService.class ) );
    }
}
Widget:
Code:
public class MyWidget extends AppWidgetProvider
{
    public static final int UPDATETIME = 1;
    
    @Override
    public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds )
    {
        context.startService( new Intent( context, MyService.class ) );
    }
    
    @Override
    public void onEnabled( Context context )
    {
        Intent intent = new Intent( MyService.BROADCAST_ACTION );
        PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 234567, intent, 0 );
        AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE );
        alarmManager.setRepeating( AlarmManager.RTC, System.currentTimeMillis(), 1000 * 60 * UPDATETIME, pendingIntent );
    }
    
    @Override
    public void onDisabled( Context context )
    {
        Intent intent = new Intent( MyService.BROADCAST_ACTION );
        PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 234567, intent, 0 );
        AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE );
        alarmManager.cancel( pendingIntent );
    }
}
Hier die relevanten Teile aus der AndroidManifest.xml:
Code:
<receiver android:name=".MyWidget">
		    <intent-filter>
		        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
		    </intent-filter>
		    <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider_4_1" />
		</receiver>
		<service android:name=".MyService"></service>
		<receiver android:name=".MyReceiver">
		    <intent-filter>
		        <action android:name="myaction"/>
		    </intent-filter>
		</receiver>

Danke für die Mithilfe!
Sollte mein Code nicht optimal sein, bitte ich um Verbesserungsvorschläge.
 

Ähnliche Themen

wernho
Antworten
11
Aufrufe
604
wernho
wernho
netfreak
  • netfreak
Antworten
10
Aufrufe
437
netfreak
netfreak
M
  • maksimilian
Antworten
15
Aufrufe
1.649
maksimilian
M
Zurück
Oben Unten