Android-Applikationen mit Fabric erweitern

Von Twitter für Twitter

Tam Hanna

© Shutterstock.com / Twin Design

Wer seine Android-Applikation um Twitter-bezogene Funktionen erweitern wollte, der tat dies bisher mit einer Gruppe von Java-Bibliotheken, die von Drittanbietern bereitgestellt werden. Twitters offizielle Lösung Fabric ist eine modulare Entwicklungssuite für verschiedene Plattformen – zwar etwas komplizierter als etwa Twitter4J, aber durchaus eine Alternative.

Wenn Influenza eine Handcomputerapplikation wäre, so hätte sie einen sicheren Platz in jeder Topliste. Dank der Selbstverbreitungsfähigkeit müsste der Entwickler nicht einmal Geld in Marketing investieren. Das Geheimnis dieses Erfolgs liegt in einer Eigenschaft, die in der Fachsprache als „Viralität“ beschrieben wird. Virale Produkte sind so aufgebaut, dass sie von ihren Nutzern entweder freiwillig oder unfreiwillig weiterverbreitet werden. Im Fall des in der Einleitung genannten Grippevirus erfolgt die Verbreitung durch Husten. Handcomputerviren wie Cabir verbreiteten sich per Bluetooth: Wenn der „User“ herumlief, wurde das Programm an die Umgebung verschickt.

Anreize für Viralität

Rapide steigende Kosten für die Akquise führten dazu, dass Entwickler „legitimer“ Programme ihre Kunden als Promoter einspannen. Dies ist nicht nur aus finanzieller Sicht attraktiv: Denn Menschen reagieren auf Empfehlungen von Freunden und Kollegen wohl eher als auf Inserate und Werbefilme.

Manche Systeme sind schon in ihren Wurzeln viral. Der verschlüsselte IM-Dienst Threema kann als ein ideales Beispiel dafür herangezogen werden. Der Dienst lässt sich nur dann effizient nutzen, wenn er von allen Kommunikationspartnern verwendet wird. Wer sich nicht von der Regierung auf die Finger schauen lassen will, wird seine Freunde zur Nutzung dieses Dienstes motivieren.

Leider sind sowohl Spiele als auch Geschäftsapplikationen nur selten Selbstläufer: Ein Nutzer eines lediglich offline spielbaren Jezzball-Klons hat nur wenig davon, wenn seine Freunde das Spiel ebenfalls spielen. Die hier fehlende „innere Motivation“ lässt sich durch externe Anreize ausgleichen. So könnte ein Programm das Absenden von Tweets mit normalerweise nur per In-App-Kauf erhältlichen Items belohnen: Wer kein Geld investieren möchte, der spammt seine Freunde voll (Abb. 1).

Abb. 1: TunnelBear belohnt twitternde User mit zusätzlichem Freivolumen

Abb. 1: TunnelBear belohnt twitternde User mit zusätzlichem Freivolumen

Insbesondere bei Teenagern ist es hilfreich, sich das Gruppenverhalten zu Nutze zu machen. Erreichte Levels und gewonnene Einsätze sollten sich per Twitter und Facebook mit Freunden teilen lassen. Personen mit einem großen Mitteilungsbedürfnis haben vielleicht Freunde, die sich durch das Veröffentlichen eines Erfolgs zum Mitmachen animieren lassen.

Wieso Twitter?

Germanisten und Psychologen kritisieren Twitter gleichermaßen: Der Nachrichtendienst ist aufgrund seiner auf 140 Zeichen beschränkten Meldungen mit Sicherheit nicht jedermanns Sache. In dieser Zeichenbeschränkung liegt aber auch ein Vorteil: Für Twitter-User ist es vergleichsweise einfach, (attraktive) Meldungen zu verbreiten. Die unkomplizierteste Nachricht stellt Abbildung 2 dar. Sie besteht nur aus Text, der in der Timeline des Benutzers und der seiner Abonnenten angezeigt wird.

Abb. 2: Kurznachrichten werden als Tweet bezeichnet

Abb. 2: Kurznachrichten werden als Tweet bezeichnet

Twitter bietet Nutzern die Möglichkeit, ihre Kurzmeldungen mit so genannten Hashtags zu verschlagworten. Abbildung 3 zeigt einen Tweet, der zwei Schlagwörter enthält – wer nach AMD oder Kinect2 sucht, wird auf diese Kurznachricht stoßen.

Abb. 3: Mit # beginnende Wörter dienen als Hashtag

Abb. 3: Mit # beginnende Wörter dienen als Hashtag

Einzelne Nutzer können durch das Voranstellen eines „@“ angesprochen werden. Dabei gibt es eine Falle, die Anfänger oftmals Aufmerksamkeit abverlangt. Eine mit einem @ beginnende Nachricht erscheint nur in der Timeline des Nutzers, an den sie adressiert ist. Für andere Personen ist sie nur dann sichtbar, wenn sie das Profil des Absenders danach durchsuchen.

Twitter los!

Wer seine Android-Applikation um Twitter-bezogene Funktionen erweitern wollte, der tat dies bisher mit einer Gruppe von Java-Bibliotheken, die von Drittanbietern bereitgestellt werden. Diese funktionieren – zumindest momentan – problemlos, was allerdings kein Garant dafür ist, dass Twitter die Bibliotheken nicht irgendwann aussperrt. Die Debatte um Twitpic sollte Entwicklern zu denken geben.

Twitters offizielle Lösung hört auf den Namen Fabric. Der erste Schritt besteht darin, die unter https://dev.twitter.com/products/fabric befindliche Downloadseite zu besuchen. Nach der Registrierung kann einige Zeit vergehen – wenn Sie die in Abbildung 4 gezeigte Nachricht bekommen, ist Geduld erforderlich.

Abb. 4: Fabric wird „stoßweise“ freigegeben

Abb. 4: Fabric wird „stoßweise“ freigegeben

An dieser Stelle soll der natürlich über Twitter anzusprechende Support von Fabric gesondert erwähnt werden. Die Entwickler reagieren rasch und überaus kompetent auf eventuelle Fehler und Probleme: Wer mit dem SDK nicht zurechtkommt, kann eine Problemmeldung abschicken.

Das vergleichsweise langsame Rollout ist keine Marotte seitens Twitter. Das Problem liegt vielmehr darin, dass die dort zum Download angebotenen SDKs den Bedürfnissen des jeweiligen Entwicklers entsprechend optimiert sind. Sie erhalten eine Datei, die Ihre damit erstellten Applikationen automatisch bei Twitter anmeldet und mit Ihrem Konto verknüpft – das bisher notwendige manuelle Anmelden von Applikationen entfällt ab sofort.

Nach dem Eintreffen der Aktivierungs-E-Mail müssen Sie den darin enthaltenen Link anklicken. Er bringt Sie auf eine von Twitter gehostete Webseite, auf der Sie zum Auswählen der von Ihnen verwendeten IDE animiert werden. Im Fall von Eclipse folgen daraufhin einige Anweisungen, die Ihnen das Herunterladen des für die IDE vorgesehenen Plug-ins ermöglichen.

Die Webseite, die die  Anweisungen enthält, sollte während des Downloadprozesses geöffnet bleiben. Nach dem erforderlichen Neustart der Entwicklungsumgebung finden Sie im Menü ein zusätzliches Symbol, das das Aktivieren der Fabric-Integration ermöglicht. Klicken Sie darauf, um den Fabric-Assistenten zu öffnen. Nach dem Anklicken des Einschaltknopfs müssen Sie sich mit den im Internet erstellten Kontodaten einloggen. Der Assistent fragt dann nach dem die Twitter-Komponenten zu ergänzenden Projekt. Im Fenster Select a kit to install müssen Sie den Install-Knopf (neben der Rubrik Twitter) anklicken und den Lizenzbedingungen zustimmen. Wählen Sie danach Single sign on aus, und klicken Sie abermals auf OK, um die eigentliche Integration anzuwerfen.

Fabric lässt sich hierbei einige Zeit. Auf der Achtkernworkstation des Autors dauerte die Ergänzung des Projektskeletts fast zwei Minuten – während dieser Zeit erscheinen keinerlei Fortschrittsmeldungen am Bildschirm. Der Erfolg der Arbeiten lässt sich unter anderem daran ablesen, dass die onCreate-Methode der MainActivity fortan den zur Initialisierung notwendigen Code enthält:

@Override
protected void onCreate(Bundle savedInstanceState)
{
  super.onCreate(savedInstanceState);
  final TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
  Fabric.with(this, new Twitter(authConfig));
  setContentView(R.layout.activity_main);
}

Falls Sie Ihre Binärdatei mit ProGuard verschlüsseln, müssen Sie die Fabric-Bibliotheken aus der Obfuscation entnehmen. Die dazu notwendigen Änderungen anproguard.cfg sind unter https://dev.twitter.com/twitter-kit/android/twitter zusammengefasst.

Logge mich ein!

Der Twitter-API-Teil von Fabric besteht aus vier Elementen, die über das globale Twitter-Objekt angesprochen werden können. Neben dem für die Applikationslogik zuständigen Twitter-Core finden Sie hier auch zwei Klassen, die diverse Steuerelemente bereitstellen. Die über das Digits-Objekt ansprechbare alternative Authentifizierungsmethode wird in diesem Artikel nicht weiter besprochen:

TwitterCore core = Twitter.core;
TweetUi tweetUi = Twitter.tweetUi;
TweetComposer composer = Twitter.tweetComposer;
Digits digits = Twitter.digits;

Vor der Nutzung der diversen APIs muss Ihr User seine Kontodaten eingeben. Der dazu notwendige Flow sollte durch ein im SDK enthaltenes Steuerelement ausgelöst werden, das sich mit folgendem Snippet in eine Activity Ihrer Wahl implantieren lässt:

<com.twitter.sdk.android.core.identity.TwitterLoginButton
        android:id="@+id/twitter_login_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

Im zur View gehörenden Code Behind sind einige Änderungen erforderlich. OnCreate muss den Twitter-Button mit einem Event Handler versorgen, der für die Verarbeitung der im Rahmen des Log-in-Prozesses auftretenden Ereignisse zuständig ist (Listing 1).

Listing 1
private TwitterLoginButton loginButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
  . . .
  
  loginButton = (TwitterLoginButton) findViewById(R.id.twitter_login_button);
  loginButton.setCallback(new Callback() {
    @Override
    public void success(Result result) {}

    @Override
    public void failure(TwitterException exception) {}
  });
}

Das Twitter-SDK erledigt die eigentliche Arbeit des Einloggens in einer eigenen Activity. Um die Informationen entgegenzunehmen, muss die Main Activity noch um die folgende Version von onActivityResult erweitert werden:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
  super.onActivityResult(requestCode, resultCode, data);
  loginButton.onActivityResult(requestCode, resultCode, data);
}

Aufgrund eines kleinen Fehlers muss die Manifestdatei des Hauptprojekts um die Deklaration der notwendigen Activity ergänzt werden. Dies lässt sich mit folgendem Snippet bewerkstelligen, das wie jede andere Activity eingepflegt wird:

<activity
    android:name="com.twitter.sdk.android.core.identity.OAuthActivity"
    android:configChanges="orientation|screenSize"
    android:excludeFromRecents="true"
    android:exported="false" />

Unser Beispiel ist ab diesem Zeitpunkt zur Ausführung bereit. Starten Sie es im Simulator oder auf einem „echten“ Gerät. Der sich nach wie vor im Vordergrund befindende SDK-Dialog sollte den Start der Applikation erkennen. Zu schnellerer Arbeitsweise auffordernde Hinweise können ignoriert werden. Klicken Sie danach auf den SIGN IN-Knopf, um die Funktionalität des Programms zu verifizieren.

Nach der erfolgreichen Abarbeitung des Anmeldedialogs legt das SDK eine Session an. Diese wird zudem in einem von der Bibliothek selbst verwalteten Speicher gesichert, von wo sie mit folgendem Code ausgelesen werden kann:

TwitterSession session = Twitter.getSessionManager().getActiveSession(); 
TwitterAuthToken authToken = session.getAuthToken(); 
String token = authToken.token; 
String secret = authToken.secret;

Leider gibt es auch hier einen Sonderfall: wenn Sie den Twitter-Button in einem Fragment deklarieren, siehe https://dev.twitter.com/twitter-kit/android/twitter-login.

Tweets versenden

Das Absenden neuer Nachrichten ist die mit Abstand häufigste Tätigkeit  eines Nutzers einer viralen Applikation. Fabric erleichtert diese üblicherweise schwierige Aufgabe durch ein als TweetComposer bezeichnetes Steuerelement.

Es soll in unserem Beispielprogramm implementiert werden. Ergänzen Sie dazu das .xml File der Haupt-Activity um einen Button, der mit folgendem Event Handler verdrahtet wird (Listing 2).

Listing 2
Button buttonSend=(Button) findViewById(R.id.buttonSend);
buttonSend.setOnClickListener(new OnClickListener() 
{
  @Override
  public void onClick(View v) 
  {
    TweetComposer.Builder builder = new TweetComposer.Builder(myThis)
      .text("Das ist ein TestTweet vom #JavaMagazin."); 
    builder.show();
  }
});

Das genaue Verhalten dieses Dialogs hängt von der Ausführungssituation ab. Wenn die Twitter-Applikation auf dem Smartphone installiert ist, so wird sie mit der Erstellung der neuen Kurznachricht beauftragt. Sollte dies aus irgendeinem Grund nicht der Fall sein, wird stattdessen eine Web-View geöffnet. Dies kann deshalb als nicht ideale Lösung bezeichnet werden, da sich der User mitunter ein zweites Mal anmelden muss (Abb. 5).

Abb. 5: Emulatoren haben normalerweise keine Twitter-App, weshalb der Browser geöffnet wird

Abb. 5: Emulatoren haben normalerweise keine Twitter-App, weshalb der Browser geöffnet wird

Um dieses Problems zu umgehen, bieten sich die in einem folgenden Abschnitt vorgestellten kombinatorischen Lösungen an. In der Praxis sind die Auswirkungen übrigens wenig gravierend: Ein Großteil der Kunden loggt sich ohnehin irgendwann bei Twitter ein, der Browser kann somit die Session einfach weiterverwenden.

Besonders engagierte Entwickler können die abzusetzende Nachricht mit einem Bildmotiv ergänzen. Der als myImageUri übergebene URI muss auf den lokalen Speicher verweisen – es ist nicht möglich, ein auf einem Webserver befindliches File zu übergeben:

TweetComposer.Builder builder = new TweetComposer.Builder(this) 
     .text("just setting up my Fabric.") 
     .image(myImageUri);

Tweets anzeigen

Die grafische Aufbereitung von Nachrichten ist deshalb schwierig, da die Nutzer mittlerweile die von Twitter vorgegebene Designvorlage erwarten. Fabric begegnet dieser Situation durch das Anbieten von zwei vorgefertigten Komponenten, die eine oder mehrere Kurznachrichten kompakt oder in Langform darstellen.

Zwecks Ansprache der Kurznachrichten müssen Sie die als Long vorliegende Tweet-ID kennen. Sie lässt sich anhand des URLs der Message ermitteln – lautet diese beispielweise
https://twitter.com/tamhanna/status/533012056384237568, so ist die betreffende Nummer 533012056384237568.

Aus didaktischen Gründen wollen wir unser Programmbeispiel erst zur Laufzeit mit einem passenden Widget versehen. Dazu muss die onCreate-Funktion des Formulars um den in Listing 3 dargestellten Code erweitert werden.

Listing 3
final MainActivity myThis=this;
final LinearLayout myLayout = (LinearLayout) findViewById(R.id.materLayout);

final long tweetId = 533012056384237568L;
TweetUtils.loadTweet(tweetId, new LoadCallback() {
    @Override
    public void success(Tweet tweet) {
        myLayout.addView(new TweetView(myThis, tweet));
    }

    @Override
    public void failure(TwitterException exception) {
    }
});

In dieser Methode findet sich keine Raketenphysik. Wir erstellen eine neue Instanz von TweetView, die daraufhin in das in der Activity befindliche Layout wandert. Im Fall des vom Autor eigens für diesen Zweck online gestellten Tweets sieht das Resultat wie in Abbildung 6 dargestellt aus.

Abb. 6: Der Test-Tweet wurde Teil des Layouts

Abb. 6: Der Test-Tweet wurde Teil des Layouts

Wer die Darstellungs-Widgets nutzen möchte, muss dies im Rahmen der Initialisierung des Fabric-SDKs mitteilen. Dazu passen wir die with()-Methode nach folgendem Schema an:

protected void onCreate(Bundle savedInstanceState)
{
  . . .
  Fabric.with(this, new Twitter(authConfig), new TweetUi());

Die im SDK enthaltenen Steuerelemente lassen sich – unter anderem – zur Realisierung von Listen von Tweets einbinden. Weitere Informationen zu den dafür vorgesehenen Methoden werden unter https://dev.twitter.com/twitter-kit/android/tweetui dokumentiert.

Beachten Sie bitte, dass Sie diese Funktion keinesfalls zum Realisieren eines klassischen Twitter-Clients nutzen sollten. Das amerikanische Unternehmen hat ein (wirtschaftliches) Interesse daran, dass seine Kunden den mit Werbeanzeigen versehenen Client aus eigenem Haus nutzen.Wer trotzdem eine Alternative anbietet, muss mit Repressalien seitens Twitter rechnen.

E-Mail-Adresse beschaffen

Viele Nutzer mögen es nicht, auf Touchscreen-Tastaturen zu tippen – der Untergang der früher weit verbreiteten Telefone mit physischer Tastatur lässt sich aus diesem Blickwinkel heraus nicht logisch erklären.

Im E-Commerce-Umfeld gilt es seit Jahren als Fakt, dass die Reduktion von Eingaben zu einer Steigerung der Konversionsrate führt. Da die meisten Twitter-Nutzer ihr Konto mit einer E-Mail-Adresse verbinden, bietet das SDK die Möglichkeit, diese Information abzufragen.
Wir erweitern unser Beispiel um einen weiteren Button, der diese Funktion vorführt. Er wird mit folgendem Event Handler verdrahtet (Listing 4).

Listing 4
@Override
public void onClick(View v) 
{
  TwitterSession session = Twitter.getSessionManager().getActiveSession(); 
  TwitterAuthClient authClient = new TwitterAuthClient();
  authClient.requestEmail(session, new Callback() {
      @Override
      public void success(Result result) {}
      @Override
      public void failure(TwitterException exception) {}
  });
}

Bei sorgfältiger Beobachtung des hier gezeigten Codes fällt auf, dass die Abfrageroutine auch fehlschlagen kann. Hierfür kommen zwei Gründe in Frage: Erstens kann der Benutzer die vom SDK angezeigte Abfrage verweigern. Als zweite und weniger häufige Ursache gilt das Fehlen der E-Mail-Adresse. Manche Nutzer erstellen ihr Twitter-Konto unter Angabe einer Handynummer.

Beachten Sie außerdem, dass die Nutzung dieses API mitunter Sonderrechte voraussetzt. Weitere Informationen zur Anmeldung finden Sie unter: https://dev.twitter.com/twitter-kit/android/request-email.

Tieferer API-Zugriff

Unsere bisher besprochenen Routinen funktionieren problemlos, wenn der Benutzer der Applikation dem Entwickler positiv gegenübersteht. Nicht kooperative Nutzer könnten den Tweet-Composer einfach schließen oder den Inhalt der vorgegebenen Nachricht verfremden – aus „#Tamoggemon rocks“ wird im Zweifelsfall schnell „I hate #Tamoggemon“.

Der einfachste Weg zur Umgehung dieses Problems besteht darin, die Existenz des betreffenden Tweets nachträglich zu verifizieren. Da das Fabric-SDK von Haus aus keine Möglichkeit zum Download aller in einem Benutzerkonto befindlichen Nachrichten anbietet, müssen wir stattdessen auf das native API zugreifen.

Fabric bietet mit Retrofit eine einfache Möglichkeit, die zum Hinzufügen eigener Endpoints geradezu prädestiniert ist. Als ersten Akt müssen Sie Ihr Programm um einen API-Client erweitern. Es handelt sich dabei um eine Art Wrapper-Klasse, die Retrofit beim Realisieren der Zugriffslogik unterstützt (Listing 5).

Listing 5
public class SUSTwitterClient extends TwitterApiClient 
{

  public SUSTwitterClient(Session session) 
  {
    super(session);
  }

    public SUSListService getListService() {
        return getService(SUSListService.class);
    }
}

Die eigentliche Intelligenz muss in Form eines Interfaces zugeführt werden. Im Fall des user_timeline-Endpoints sieht die notwendige Struktur folgendermaßen aus:

public interface SUSListService 
{
  public static class TimeLineItem
  {
    ArrayList tweets;
  }
  @GET("/1.1/statuses/user_timeline.json?count=10")
  void myItems(com.twitter.sdk.android.core.Callback cb);
}

Damit fehlt nur noch der Event Handler, der für das Aktivieren der soeben errichteten Struktur zuständig ist. Er beginnt – wie sollte es auch anders sein – mit dem Beschaffen eines Session-Objekts. Dieses wird danach für die Erstellung des ListServices eingespannt (Listing 6).

Listing 6
private void loadTweets() 
{
  TwitterSession session = Twitter.getSessionManager().getActiveSession();
  SUSTwitterClient myClient=new SUSTwitterClient(session);
  myClient.getListService().myItems(new com.twitter.sdk.android.core.Callback () 
  {
    @Override
    public void failure(TwitterException arg0) 
    {
            Log.v("MainActivity", arg0.getMessage());
    }

Im Fall der erfolgreichen Abarbeitung des Befehls wirft unser Beispiel die vom Server erhaltenen Tweets in die Debugger-Konsole aus. In einem realen Programm sollten Sie die zurückgegebenen Werte auswerten und dem Benutzer bei Bedarf seine Belohnung zugestehen (Listing 7).

Listing 7
@Override
public void success(Result searchResult)
{
   JSONArray json_array = new JSONArray(searchResult.data);
   for (int i = 0; i < json_array.length(); i++) {
     try 
     {
       JSONObject item = json_array.getJSONObject(i);
       String tweet_text = item.getString("text");
       System.out.println(tweet_text);
     } 
     catch (JSONException e) 
     {
       e.printStackTrace();
     }
   }
}

Besonders misstrauische Personen könnten diese Arbeit am Server erledigen: In diesem Fall muss der Twitter-Name des Benutzers zwecks Kontrolle hochgeladen werden. Bei „immateriellen Gütern“ ist dieser Aufwand nur wenig sinnvoll, da jeder kompetente Cracker daran denkt, seinen Nutzern ausreichend In-App Purchase Items zur Verfügung zu stellen.

Kombinatorische Lösungen

Wer seine Applikation händisch bei Twitter authentifiziert, wird möglicherweise erschrecken. Denn die Abarbeitung der diversen OAuth-Flows ist alles andere als einfach. Fabric nimmt Ihnen diese lästige Aufgabe ab.

Sie können die zum Zugriff berechtigenden Sessionwerte wie im Abschnitt „Logge mich ein“ extrahieren und für eigene Requests verwenden. Natürlich spricht aus technischer Sicht nichts dagegen, diese Informationen zum Absenden eigener Befehle per Twitter4J zu nutzen: So entsteht das ein oder andere Feature, das per Fabric nur kompliziert zu realisieren gewesen wäre.

Fazit

Der Aufwand für die Integration von Twitter hält sich in Grenzen. Wer sein Programm in Zeiten von rapide steigenden Kosten pro User nicht mit viralen Funktionen ausstattet, verzichtet auf leicht verdientes Geld.

Fabric ist an manchen Stellen umständlicher als beispielsweise Twitter4J. Der etwas höhere Entwicklungsaufwand bringt jedoch eine wesentlich größer einzuschätzende Zukunftssicherheit: Es wäre nicht schön, wenn Ihre Nutzer eines Tages keine neuen Werbenachrichten an ihre Kollegen verschicken könnten.

Aufmacherbild: Twin Design / Shutterstock.com

Geschrieben von
Tam Hanna
Tam Hanna
Tam Hanna befasst sich seit der Zeit des Palm IIIc mit der Programmierung und Anwendung von Handcomputern. Er entwickelt Programme für diverse Plattformen, betreibt Onlinenewsdienste zum Thema und steht unter tamhan@tamoggemon.com für Fragen, Trainings und Vorträge gern zur Verfügung.
Kommentare

Hinterlasse einen Kommentar

avatar
4000
  Subscribe  
Benachrichtige mich zu: