Widget erstellen - Android Java

Widget erstellen - Android Java

Heute wollen wir uns einmal mit der Thematik der Widgets unter Android beschäftigen und ein ganz simples aber funktionsfähiges Widget programmieren.

Unser Ziel wird es sein ein Widget zu programmieren, dass zwar ganz normal funktioniert, der Einfachheit halber aber nichts kann.

Vorbereitungen

Bevor wir mit unserem ersten Widget beginnen können, bedarf es ein paar wenigen Vorbereitungen.

Informationen

Zu aller erst müssen wir eine Datei zur Verfügung stellen, nach der Android weiß, um welches Widget es sich handelt, wie es heißt, wie groß es minimal und maximal sein darf, welche Klasse die Arbeit übernimmt und in welchen Intervallen unser Widget erneuert werden soll.

Wir erstellen also eine Datei namens “widget_info.xml”, indem wir sie in den Ordner res -> xml packen.
Besteht dieser Ordner noch nicht können wir ihn getrost selber erstellen.

Der Inhalt der neu erstellten Datei sieht bei mit wie folgt aus:

<!--?xml version="1.0" encoding="utf-8"?-->
<!--
 ~ Copyright 2016 www.droid-lernen.de
 ~
 ~ Licensed under the Apache License, Version 2.0 (the „License“);
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~ http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an „AS IS“ BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minwidth="40dp" android:minheight="40dp" android:updateperiodmillis="86400000" android:previewimage="@drawable/widget_bild" android:initiallayout="@layout/beispiel_widget_loading_layout" android:resizemode="horizontal|vertical" android:widgetcategory="home_screen">
</appwidget-provider>

Über “updatePeriodMillis” legen wir fest, wie häufig das Widget erneuert werden soll. Die Angabe ist in Millisekunden zu machen. Wichtig wäre zu beachten, dass Android das Gerät jedes mal aufweckt, wenn dieser Intervall erreicht ist. Bitte bedenkt, dass jedes Aufwecken den Nutzer Akku kostet.

“previewImage” beschreibt den Pfad zu einem Vorschaubild des Widgets, welches im Widget-Auswahlmenü angezeigt wird. Wählt dieses Bild weise, nicht zu groß und nicht zu klein und achtet darauf, dass es nach Möglichkeit nur eine wirkliche Vorschau ohne Schnickschnack anzeigt.

Zu guter letzt möchte ich noch “initialLayout” ansprechen. Dieses Layout wird als Widget angezeigt, bevor das Widget wirklich geladen wurde. Das Widget ist genau dann geladen, wenn unsere Widget Klasse die Funktion “onUpdate” fertig ausgeführt hat und das kann etwas länger dauern. Später dazu mehr.
Es wäre Vorteilhaft, wenn ihr hier ein Layout angebt, welches Beispielsweise einen Text wie “Wird geladen…” oder ähnliches anzeigt.

Design

Wie bereits angesprochen werden wir zwei Layout Dateien benötigen. Dies ist zwar nicht zwangsläufig nötig, aber hilfreich.

beispiel_widget_loading_layout.xml:


<!--?xml version="1.0" encoding="utf-8"?-->
<!--
 ~ Copyright 2016 www.droid-lernen.de
 ~
 ~ Licensed under the Apache License, Version 2.0 (the „License“);
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~ http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an „AS IS“ BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">

 <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textappearance="?android:attr/textAppearanceMedium" android:text="Wird geladen ..." android:id="@+id/textView" android:layout_gravity="center_horizontal"></textview>
</linearlayout>

beispiel_widget_layout.xml:


<!--?xml version="1.0" encoding="utf-8"?-->
<!--
 ~ Copyright 2016 www.droid-lernen.de
 ~
 ~ Licensed under the Apache License, Version 2.0 (the „License“);
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~
 ~ http://www.apache.org/licenses/LICENSE-2.0
 ~
 ~ Unless required by applicable law or agreed to in writing, software
 ~ distributed under the License is distributed on an „AS IS“ BASIS,
 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ~ See the License for the specific language governing permissions and
 ~ limitations under the License.
 -->

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">

 <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:textappearance="?android:attr/textAppearanceMedium" android:text="Medium Text" android:id="@+id/widget_text" android:layout_gravity="center_horizontal"></textview>
</linearlayout>

Die beiden Dateien sehen jetzt sehr ähnlich aus -sind sie ja auch- , aber für dieses einfache Beispiel reicht es aus.
Wir zeigen während des Ladens den Text “Wird geladen …” an und anschließend eine Textbox an selbiger Stelle, mit anderem Text.

Bild

Wie bereits angesprochen benötigen wir ein Vorschaubild.
Hier nehmen wir einfach mal ein 400 x 400 Pixel großes Bild:

widget_bild

Android Manifest

Wir haben ja bereits definiert, welche Informationen über unsere Widget an Android weitergegeben werden sollen.
Damit diese Informationen auch wirklich bei Android ankommen und Android überhaupt weiß, dass unsere App ein Widget enthält müssen wir diese Information ebenfalls angeben.
Hierzu öffnen wir die Android-Manifest.xml Datei und fügen innerhalb des “application”-Tags ein:

<receiver android:name=".BeispielWidget">
 <intent-filter>
 <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
 </intent-filter>
 <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info">
</meta-data></receiver>

Widget Klasse

Zu guter letzt bedarf es der eigentlichen Widget-Klasse.
Diese enthält die eigentliche Logik des Widgets.
Ich werde sie mal ohne weitere Erläuterungen veröffentlichen, die Kommentare innerhalb der Klasse sprechen für sich:

/*
 * Copyright 2016 www.droid-lernen.de
 *
 * Licensed under the Apache License, Version 2.0 (the „License“);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an „AS IS“ BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.droid_lernen.widgeterstellen;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.os.Bundle;
import android.widget.RemoteViews;

public class BeispielWidget extends AppWidgetProvider {

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

    // Perform this loop procedure for each App Widget that belongs to this provider
    for (int i=0; i<n; i++){
      int appWidgetId = appWidgetIds[i];

      // Get the layout for the App Widget and attach an on-click listener
      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.beispiel_widget_layout);

      // Tell the AppWidgetManager to perform an update on the current app widget
      appWidgetManager.updateAppWidget(appWidgetId, views);
    }
  }

  @Override
  public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);

    // Diese Funktion wird aufgerufen, wenn das Widget verschoben oder in der Größe verändert wird.

  }

  @Override
  public void onDeleted(Context context, int[] appWidgetIds) {
    super.onDeleted(context, appWidgetIds);

    // Diese Funktion wird aufgerunfen, wenn das Widget vom Homescreen gelöscht wird.
    // Es können weiterhin noch andere Widgets der App auf dem Homescreen sein.

  }

  @Override
  public void onDisabled(Context context) {
    super.onDisabled(context);

    // Diese Funktion wird aufgerunfen, wenn ALLE Widgets, die einmal auf dem Homescreen waren entfernt werden.
    // Bitte erst hier alle Vorbereitungen, aus onEnabled, rückgängig machen.

  }

  @Override
  public void onEnabled(Context context) {
    super.onEnabled(context);

    // Diese Funktion wird aufgerunfen, wenn das Widget auf dem Homescreen gesetzt wird.
    // Hier sollten noch Möglichkeit Vorbereitungen, für die Nutzung des Widgets getroffen werden.

  }

  @Override
  public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
    super.onRestored(context, oldWidgetIds, newWidgetIds);
  }
}


Marvin

Ich bin ein Mensch, der sich neben der Programmierung noch für tausend andere Dinge interessiert, die mal mehr und mal weniger verrückt sind. Vor allem aber bin ich Feuer und Flamme mit der Programmierung von eigenen kleinen Apps und Programmen, die mein Leben bereichern.

Hat dir dieser Artikel gefallen?

Kommentar hinzufügen

*Pflichtfeld