Så här använder du Azure Mobile Apps SDK för Android
Den här guiden visar hur du använder Android-klient-SDK för mobilappar för att implementera vanliga scenarier, till exempel:
- Fråga efter data (infoga, uppdatera och ta bort).
- Autentisering.
- Hantera fel.
- Anpassa klienten.
Den här guiden fokuserar på Android SDK på klientsidan. Mer information om SDK:er på serversidan för Mobilappar finns i Arbeta med .NET-serverdels-SDK eller Så här använder du Node.js serverdels-SDK.
Referensdokumentation
Du hittar API-referensen för Javadocs för Android-klientbiblioteket på GitHub.
Plattformar som stöds
Azure Mobile Apps SDK för Android stöder API-nivåer 19 till och med 24 (KitKat via Nougat) för formfaktorer för telefoner och surfplattor. I synnerhet autentisering använder en vanlig webbramverksmetod för att samla in autentiseringsuppgifter. Serverflödesautentisering fungerar inte med små formfaktorenheter som klockor.
Installation och förutsättningar
Slutför snabbstartsguiden för Mobilappar. Den här uppgiften säkerställer att alla förutsättningar för att utveckla Azure Mobile Apps har uppfyllts. Snabbstarten hjälper dig också att konfigurera ditt konto och skapa din första mobile app-serverdel.
Om du bestämmer dig för att inte slutföra snabbstartsguiden utför du följande uppgifter:
- skapa en mobilappsserverdel som ska användas med din Android-app.
- Uppdatera Gradle-byggfilerna i Android Studio.
- Aktivera internetbehörighet.
Uppdatera Gradle-build-filen
Ändra båda build.gradle-filerna :
Lägg till den här koden i filen build.gradle på projektnivå:
buildscript { repositories { jcenter() google() } } allprojects { repositories { jcenter() google() } }
Lägg till den här koden i filen build.gradle på modulappnivå i taggen beroenden:
implementation 'com.microsoft.azure:azure-mobile-android:3.4.0@aar'
För närvarande är den senaste versionen 3.4.0. De versioner som stöds visas i bintray.
Aktivera internetbehörighet
För att få åtkomst till Azure måste din app ha internetbehörighet aktiverad. Om den inte redan är aktiverad lägger du till följande kodrad i filen AndroidManifest.xml :
<uses-permission android:name="android.permission.INTERNET" />
Skapa en klientanslutning
Azure Mobile Apps har fyra funktioner för ditt mobilprogram:
- Dataåtkomst och offlinesynkronisering med en Azure Mobile Apps-tjänst.
- Anropa anpassade API:er som skrivits med Azure Mobile Apps Server SDK.
- Autentisering med Azure App Service-autentisering och auktorisering.
- Push-meddelanderegistrering med Notification Hubs.
Var och en av dessa funktioner kräver först att du skapar ett MobileServiceClient
objekt. Endast ett MobileServiceClient
objekt ska skapas i din mobila klient (det vill sägs att det ska vara ett Singleton-mönster). Så här skapar du ett MobileServiceClient
objekt:
MobileServiceClient mClient = new MobileServiceClient(
"<MobileAppUrl>", // Replace with the Site URL
this); // Your application Context
<MobileAppUrl>
är antingen en sträng eller ett URL-objekt som pekar på din mobila serverdel. Om du använder Azure App Service som värd för din mobila serverdel kontrollerar du att du använder den säkra https://
versionen av URL:en.
Klienten kräver också åtkomst till aktiviteten eller kontexten – parametern this
i exemplet. MobileServiceClient-konstruktionen onCreate()
bör ske inom metoden för den aktivitet som refereras i AndroidManifest.xml
filen.
Vi rekommenderar att du abstraherar serverkommunikationen till en egen klass (singleton-pattern). I det här fallet bör du skicka aktiviteten i konstruktorn för att konfigurera tjänsten på rätt sätt. Till exempel:
package com.example.appname.services;
import android.content.Context;
import com.microsoft.windowsazure.mobileservices.*;
public class AzureServiceAdapter {
private String mMobileBackendUrl = "https://myappname.azurewebsites.net";
private Context mContext;
private MobileServiceClient mClient;
private static AzureServiceAdapter mInstance = null;
private AzureServiceAdapter(Context context) {
mContext = context;
mClient = new MobileServiceClient(mMobileBackendUrl, mContext);
}
public static void Initialize(Context context) {
if (mInstance == null) {
mInstance = new AzureServiceAdapter(context);
} else {
throw new IllegalStateException("AzureServiceAdapter is already initialized");
}
}
public static AzureServiceAdapter getInstance() {
if (mInstance == null) {
throw new IllegalStateException("AzureServiceAdapter is not initialized");
}
return mInstance;
}
public MobileServiceClient getClient() {
return mClient;
}
// Place any public methods that operate on mClient here.
}
Nu kan du anropa AzureServiceAdapter.Initialize(this);
metoden för onCreate()
din huvudaktivitet. Andra metoder som behöver åtkomst till klienten använder AzureServiceAdapter.getInstance();
för att hämta en referens till tjänstkortet.
Dataåtgärder
Kärnan i Azure Mobile Apps SDK är att ge åtkomst till data som lagras i SQL Azure på mobilappens serverdel. Du kan komma åt dessa data med hjälp av starkt skrivna klasser (rekommenderas) eller otypade frågor (rekommenderas inte). Huvuddelen av det här avsnittet handlar om att använda starkt skrivna klasser.
Definiera klientdataklasser
Om du vill komma åt data från SQL Azure-tabeller definierar du klientdataklasser som motsvarar tabellerna i mobilappens serverdel. Exempel i det här avsnittet förutsätter en tabell med namnet MyDataTable, som har följande kolumner:
- id
- text
- slutfört
Motsvarande typerade objekt på klientsidan finns i en fil med namnet MyDataTable.java:
public class ToDoItem {
private String id;
private String text;
private Boolean complete;
}
Lägg till metoder för getter och setter för varje fält som du lägger till. Om din SQL Azure-tabell innehåller fler kolumner lägger du till motsvarande fält i den här klassen. Om DTO (dataöverföringsobjektet) till exempel hade en heltalskolumn med prioritet kan du lägga till det här fältet tillsammans med dess metoder för getter och setter:
private Integer priority;
/**
* Returns the item priority
*/
public Integer getPriority() {
return mPriority;
}
/**
* Sets the item priority
*
* @param priority
* priority to set
*/
public final void setPriority(Integer priority) {
mPriority = priority;
}
Information om hur du skapar ytterligare tabeller i mobile apps-serverdelen finns i Så här definierar du en tabellstyrenhet (.NET-serverdel) eller Definiera tabeller med ett dynamiskt schema (Node.js serverdel).
En Azure Mobile Apps-serverdelstabell definierar fem specialfält, varav fyra är tillgängliga för klienter:
String id
: Det globalt unika ID:t för posten. Vi rekommenderar att du gör ID:t till Strängrepresentation av ett UUID-objekt .DateTimeOffset updatedAt
: Datum/tid för den senaste uppdateringen. Fältet updatedAt anges av servern och bör aldrig anges av klientkoden.DateTimeOffset createdAt
: Datum/tid då objektet skapades. Fältet createdAt anges av servern och bör aldrig anges av klientkoden.byte[] version
: Normalt representerad som en sträng anges även versionen av servern.boolean deleted
: Anger att posten har tagits bort men inte rensats ännu. Använd intedeleted
som en egenskap i din klass.
Fältet id
är obligatoriskt. Fältet updatedAt
och version
fältet används för offlinesynkronisering (för inkrementell synkronisering respektive konfliktlösning). Fältet createdAt
är ett referensfält och används inte av klienten. Namnen är "across-the-wire"-namn på egenskaperna och kan inte justeras. Du kan dock skapa en mappning mellan objektet och namnen "över tråden" med hjälp av gson-biblioteket . Till exempel:
package com.example.zumoappname;
import com.microsoft.windowsazure.mobileservices.table.DateTimeOffset;
public class ToDoItem
{
@com.google.gson.annotations.SerializedName("id")
private String mId;
public String getId() { return mId; }
public final void setId(String id) { mId = id; }
@com.google.gson.annotations.SerializedName("complete")
private boolean mComplete;
public boolean isComplete() { return mComplete; }
public void setComplete(boolean complete) { mComplete = complete; }
@com.google.gson.annotations.SerializedName("text")
private String mText;
public String getText() { return mText; }
public final void setText(String text) { mText = text; }
@com.google.gson.annotations.SerializedName("createdAt")
private DateTimeOffset mCreatedAt;
public DateTimeOffset getCreatedAt() { return mCreatedAt; }
protected void setCreatedAt(DateTimeOffset createdAt) { mCreatedAt = createdAt; }
@com.google.gson.annotations.SerializedName("updatedAt")
private DateTimeOffset mUpdatedAt;
public DateTimeOffset getUpdatedAt() { return mUpdatedAt; }
protected void setUpdatedAt(DateTimeOffset updatedAt) { mUpdatedAt = updatedAt; }
@com.google.gson.annotations.SerializedName("version")
private String mVersion;
public String getVersion() { return mVersion; }
public final void setVersion(String version) { mVersion = version; }
public ToDoItem() { }
public ToDoItem(String id, String text) {
this.setId(id);
this.setText(text);
}
@Override
public boolean equals(Object o) {
return o instanceof ToDoItem && ((ToDoItem) o).mId == mId;
}
@Override
public String toString() {
return getText();
}
}
Skapa en tabellreferens
Om du vill komma åt en tabell skapar du först ett MobileServiceTable-objekt genom att anropa metoden getTable på MobileServiceClient. Den här metoden har två överlagringar:
public class MobileServiceClient {
public <E> MobileServiceTable<E> getTable(Class<E> clazz);
public <E> MobileServiceTable<E> getTable(String name, Class<E> clazz);
}
I följande kod är mClient en referens till ditt MobileServiceClient-objekt. Den första överlagringen används där klassnamnet och tabellnamnet är samma och är den som används i snabbstarten:
MobileServiceTable<ToDoItem> mToDoTable = mClient.getTable(ToDoItem.class);
Den andra överlagringen används när tabellnamnet skiljer sig från klassnamnet: den första parametern är tabellnamnet.
MobileServiceTable<ToDoItem> mToDoTable = mClient.getTable("ToDoItemBackup", ToDoItem.class);
Fråga en serverdelstabell
Hämta först en tabellreferens. Kör sedan en fråga i tabellreferensen. En fråga är en kombination av:
- En
.where()
filtersats. - En
.orderBy()
beställningssats. - En
.select()
fältvalssats. - A
.skip()
och.top()
för sidsidiga resultat.
Satserna måste presenteras i föregående ordning.
Filtrera resultat
Den allmänna formen av en fråga är:
List<MyDataTable> results = mDataTable
// More filters here
.execute() // Returns a ListenableFuture<E>
.get() // Converts the async into a sync result
Föregående exempel returnerar alla resultat (upp till den maximala sidstorlek som angetts av servern). Metoden .execute()
kör frågan på serverdelen. Frågan konverteras till en OData v3-fråga innan den överförs till Mobile Apps-serverdelen. Vid mottagandet konverterar Mobile Apps-serverdelen frågan till en SQL-instruktion innan den körs på SQL Azure-instansen. Eftersom nätverksaktiviteten tar lite tid .execute()
returnerar metoden en ListenableFuture<E>
.
Filtrera returnerade data
Följande frågekörning returnerar alla objekt från tabellen ToDoItem där fullständig är lika med false.
List<ToDoItem> result = mToDoTable
.where()
.field("complete").eq(false)
.execute()
.get();
mToDoTable är referensen till den mobiltjänsttabell som vi skapade tidigare.
Definiera ett filter med hjälp av where-metodens anrop i tabellreferensen. Var metoden följs av en fältmetod följt av en metod som anger det logiska predikatet. Möjliga predikatmetoder inkluderar eq (lika med), ne (inte lika), gt (större än), ge (större än eller lika med), lt (mindre än), le (mindre än eller lika med). Med de här metoderna kan du jämföra tal- och strängfält med specifika värden.
Du kan filtrera efter datum. Med följande metoder kan du jämföra hela datumfältet eller delar av datumet: år, månad, dag, timme, minut och sekund. I följande exempel läggs ett filter för objekt vars förfallodatum är lika med 2013.
List<ToDoItem> results = MToDoTable
.where()
.year("due").eq(2013)
.execute()
.get();
Följande metoder stöder komplexa filter på strängfält: startsWith, endsWith, concat, subString, indexOf, replace, toLower, toUpper, trim och length. I följande exempel filtreras tabellrader där textkolumnen börjar med "PRI0".
List<ToDoItem> results = mToDoTable
.where()
.startsWith("text", "PRI0")
.execute()
.get();
Följande operatormetoder stöds i nummerfält: add, sub, mul, div, mod, floor, ceiling och round. I följande exempel filtreras tabellrader där varaktigheten är ett jämnt tal.
List<ToDoItem> results = mToDoTable
.where()
.field("duration").mod(2).eq(0)
.execute()
.get();
Du kan kombinera predikat med dessa logiska metoder: och eller inte. I följande exempel kombineras två av föregående exempel.
List<ToDoItem> results = mToDoTable
.where()
.year("due").eq(2013).and().startsWith("text", "PRI0")
.execute()
.get();
Gruppera och kapsla logiska operatorer:
List<ToDoItem> results = mToDoTable
.where()
.year("due").eq(2013)
.and(
startsWith("text", "PRI0")
.or()
.field("duration").gt(10)
)
.execute().get();
Mer detaljerad information och exempel på filtrering finns i Utforska rikedomen i Android-klientfrågemodellen.
Sortera returnerade data
Följande kod returnerar alla objekt från en tabell med ToDoItems sorterade stigande efter textfältet . mToDoTable är referensen till den serverdelstabell som du skapade tidigare:
List<ToDoItem> results = mToDoTable
.orderBy("text", QueryOrder.Ascending)
.execute()
.get();
Den första parametern för metoden orderBy är en sträng som är lika med namnet på det fält som ska sorteras. Den andra parametern använder QueryOrder-uppräkningen för att ange om stigande eller fallande ska sorteras. Om du filtrerar med hjälp av where-metoden måste metoden where anropas före metoden orderBy.
Välj specifika kolumner
Följande kod visar hur du returnerar alla objekt från en tabell med ToDoItems, men visar bara de fullständiga fälten och textfälten. mToDoTable är referensen till den serverdelstabell som vi skapade tidigare.
List<ToDoItemNarrow> result = mToDoTable
.select("complete", "text")
.execute()
.get();
Parametrarna för funktionen Select är strängnamnen för tabellens kolumner som du vill returnera. Metoden Select måste följa metoder som where och orderBy. Det kan följas av växlingsmetoder som hoppa över och överst.
Returnera data på sidor
Data returneras ALLTID på sidor. Det maximala antalet poster som returneras anges av servern. Om klienten begär fler poster returnerar servern det maximala antalet poster. Som standard är den maximala sidstorleken på servern 50 poster.
Det första exemplet visar hur du väljer de fem översta objekten från en tabell. Frågan returnerar objekten från en tabell med ToDoItems. mToDoTable är referensen till den serverdelstabell som du skapade tidigare:
List<ToDoItem> result = mToDoTable
.top(5)
.execute()
.get();
Här är en fråga som hoppar över de första fem objekten och sedan returnerar följande fem:
List<ToDoItem> result = mToDoTable
.skip(5).top(5)
.execute()
.get();
Om du vill hämta alla poster i en tabell implementerar du kod för att iterera över alla sidor:
List<MyDataModel> results = new ArrayList<>();
int nResults;
do {
int currentCount = results.size();
List<MyDataModel> pagedResults = mDataTable
.skip(currentCount).top(500)
.execute().get();
nResults = pagedResults.size();
if (nResults > 0) {
results.addAll(pagedResults);
}
} while (nResults > 0);
En begäran för alla poster med den här metoden skapar minst två begäranden till Mobile Apps-serverdelen.
Dricks
Att välja rätt sidstorlek är en balans mellan minnesanvändningen medan begäran sker, bandbreddsanvändning och fördröjning när data tas emot helt. Standardvärdet (50 poster) är lämpligt för alla enheter. Om du uteslutande arbetar på större minnesenheter ökar du med upp till 500. Vi har upptäckt att en ökning av sidstorleken utöver 500 poster resulterar i oacceptabla fördröjningar och stora minnesproblem.
Anvisningar: Sammanfoga frågemetoder
De metoder som används för att fråga serverdelstabeller kan sammanfogas. Genom att länka frågemetoder kan du välja specifika kolumner med filtrerade rader som är sorterade och sidiga. Du kan skapa komplexa logiska filter. Varje frågemetod returnerar ett frågeobjekt. Om du vill avsluta serien med metoder och faktiskt köra frågan anropar du körningsmetoden . Till exempel:
List<ToDoItem> results = mToDoTable
.where()
.year("due").eq(2013)
.and(
startsWith("text", "PRI0").or().field("duration").gt(10)
)
.orderBy(duration, QueryOrder.Ascending)
.select("id", "complete", "text", "duration")
.skip(200).top(100)
.execute()
.get();
De länkade frågemetoderna måste ordnas på följande sätt:
- Filtrera (var) metoder.
- Sorteringsmetoder (orderBy).
- Urvalsmetoder (välj).
- växlingsmetoder (hoppa över och överst).
Binda data till användargränssnittet
Databindningen omfattar tre komponenter:
- Datakällan
- Skärmlayouten
- Adaptern som binder ihop de två.
I vår exempelkod returnerar vi data från Mobile Apps SQL Azure-tabellen ToDoItem till en matris. Den här aktiviteten är ett vanligt mönster för dataprogram. Databasfrågor returnerar ofta en samling rader som klienten får i en lista eller matris. I det här exemplet är matrisen datakällan. Koden anger en skärmlayout som definierar vyn för de data som visas på enheten. De två är bundna tillsammans med ett kort, vilket i den här koden är ett tillägg till klassen ArrayAdapter<ToDoItem> .
Definiera layouten
Layouten definieras av flera kodfragment av XML-kod. Med en befintlig layout representerar följande kod den ListView som vi vill fylla i med våra serverdata.
<ListView
android:id="@+id/listViewToDo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="@layout/row_list_to_do" >
</ListView>
I föregående kod anger attributet listitem ID för layouten för en enskild rad i listan. Den här koden anger en kryssruta och dess associerade text och instansieras en gång för varje objekt i listan. Den här layouten visar inte ID-fältet , och en mer komplex layout skulle ange ytterligare fält i visningen. Den här koden finns i filen row_list_to_do.xml .
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<CheckBox
android:id="@+id/checkToDoItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/checkbox_text" />
</LinearLayout>
Definiera adaptern
Eftersom datakällan i vår vy är en matris med ToDoItem underklassklassar vi vårt kort från en ArrayAdapter<ToDoItem-klass> . Den här underklassen skapar en vy för varje ToDoItem med hjälp av layouten row_list_to_do . I vår kod definierar vi följande klass som är ett tillägg för klassen ArrayAdapter<E> :
public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> {
}
Åsidosätt metoden getView för korten. Till exempel:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final ToDoItem currentItem = getItem(position);
if (row == null) {
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
row = inflater.inflate(R.layout.row_list_to_do, parent, false);
}
row.setTag(currentItem);
final CheckBox checkBox = (CheckBox) row.findViewById(R.id.checkToDoItem);
checkBox.setText(currentItem.getText());
checkBox.setChecked(false);
checkBox.setEnabled(true);
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (checkBox.isChecked()) {
checkBox.setEnabled(false);
if (mContext instanceof ToDoActivity) {
ToDoActivity activity = (ToDoActivity) mContext;
activity.checkItem(currentItem);
}
}
}
});
return row;
}
Vi skapar en instans av den här klassen i vår aktivitet enligt följande:
ToDoItemAdapter mAdapter;
mAdapter = new ToDoItemAdapter(this, R.layout.row_list_to_do);
Den andra parametern för konstruktorn ToDoItemAdapter är en referens till layouten. Nu kan vi instansiera ListView och tilldela adaptern till ListView.
ListView listViewToDo = (ListView) findViewById(R.id.listViewToDo);
listViewToDo.setAdapter(mAdapter);
Använd adaptern för att binda till användargränssnittet
Nu är du redo att använda databindning. Följande kod visar hur du hämtar objekt i tabellen och fyller det lokala kortet med de returnerade objekten.
public void showAll(View view) {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
final List<ToDoItem> results = mToDoTable.execute().get();
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.clear();
for (ToDoItem item : results) {
mAdapter.add(item);
}
}
});
} catch (Exception exception) {
createAndShowDialog(exception, "Error");
}
return null;
}
};
runAsyncTask(task);
}
Anropa adaptern när du ändrar ToDoItem-tabellen . Eftersom ändringar görs på arkivhandlingsbasis hanterar du en enskild rad i stället för en samling. När du infogar ett objekt anropar du lägg till-metoden på adaptern. Anropa borttagningsmetoden när du tar bort det.
Du hittar ett fullständigt exempel i Android-snabbstartsprojektet.
Infoga data i serverdelen
Instansiera en instans av klassen ToDoItem och ange dess egenskaper.
ToDoItem item = new ToDoItem();
item.text = "Test Program";
item.complete = false;
Använd sedan insert() för att infoga ett objekt:
ToDoItem entity = mToDoTable
.insert(item) // Returns a ListenableFuture<ToDoItem>
.get();
Den returnerade entiteten matchar de data som infogats i serverdelstabellen, inklusive ID:t och andra värden (till exempel fälten createdAt
, updatedAt
och version
) som angetts på serverdelen.
Mobile Apps-tabeller kräver en primärnyckelkolumn med namnet ID. Den här kolumnen måste vara en sträng. Standardvärdet för ID-kolumnen är ett GUID. Du kan ange andra unika värden, till exempel e-postadresser eller användarnamn. När ett sträng-ID-värde inte anges för en infogad post genererar serverdelen ett nytt GUID.
Sträng-ID-värden ger följande fördelar:
- ID:t kan genereras utan att göra en tur och retur-resa till databasen.
- Poster är enklare att sammanfoga från olika tabeller eller databaser.
- ID-värden integreras bättre med ett programs logik.
Sträng-ID-värden krävs för stöd för offlinesynkronisering. Du kan inte ändra ett ID när det har lagrats i serverdelsdatabasen.
Uppdatera data i en mobilapp
Om du vill uppdatera data i en tabell skickar du det nya objektet till metoden update().
mToDoTable
.update(item) // Returns a ListenableFuture<ToDoItem>
.get();
I det här exemplet är objektet en referens till en rad i tabellen ToDoItem , som har gjort vissa ändringar. Raden med samma ID uppdateras.
Ta bort data i en mobilapp
Följande kod visar hur du tar bort data från en tabell genom att ange dataobjektet.
mToDoTable
.delete(item);
Du kan också ta bort ett objekt genom att ange id-fältet på raden som ska tas bort.
String myRowId = "2FA404AB-E458-44CD-BC1B-3BC847EF0902";
mToDoTable
.delete(myRowId);
Slå upp ett specifikt objekt efter ID
Leta upp ett objekt med ett specifikt ID-fält med metoden lookUp():
ToDoItem result = mToDoTable
.lookUp("0380BAFB-BCFF-443C-B7D5-30199F730335")
.get();
Anvisningar: Arbeta med otypade data
Den otypade programmeringsmodellen ger dig exakt kontroll över JSON-serialisering. Det finns några vanliga scenarier där du kanske vill använda en otypad programmeringsmodell. Om din serverdelstabell till exempel innehåller många kolumner och du bara behöver referera till en delmängd av kolumnerna. Den typerade modellen kräver att du definierar alla kolumner som definierats i Mobile Apps-serverdelen i dataklassen. De flesta API-anrop för åtkomst till data liknar de typinskrivna programmeringsanropen. Den största skillnaden är att i den otypade modellen anropar du metoder i Objektet MobileServiceJsonTable i stället för MobileServiceTable-objektet .
Skapa en instans av en otypad tabell
Precis som den typerade modellen börjar du med att hämta en tabellreferens, men i det här fallet är det ett MobileServicesJsonTable-objekt . Hämta referensen genom att anropa metoden getTable på en instans av klienten:
private MobileServiceJsonTable mJsonToDoTable;
//...
mJsonToDoTable = mClient.getTable("ToDoItem");
När du har skapat en instans av MobileServiceJsonTable har den praktiskt taget samma API som med den inskrivna programmeringsmodellen. I vissa fall tar metoderna en otypad parameter i stället för en typad parameter.
Infoga i en otypad tabell
Följande kod visar hur du gör en infogning. Det första steget är att skapa en JsonObject, som är en del av gson-biblioteket .
JsonObject jsonItem = new JsonObject();
jsonItem.addProperty("text", "Wake up");
jsonItem.addProperty("complete", false);
Använd sedan insert() för att infoga det otypade objektet i tabellen.
JsonObject insertedItem = mJsonToDoTable
.insert(jsonItem)
.get();
Om du behöver hämta ID:t för det infogade objektet använder du metoden getAsJsonPrimitive().
String id = insertedItem.getAsJsonPrimitive("id").getAsString();
Ta bort från en otypad tabell
Följande kod visar hur du tar bort en instans, i det här fallet samma instans av en JsonObject som skapades i föregående infoga-exempel . Koden är samma som med det inskrivna fallet, men metoden har en annan signatur eftersom den refererar till en JsonObject.
mToDoTable
.delete(insertedItem);
Du kan också ta bort en instans direkt med hjälp av dess ID:
mToDoTable.delete(ID);
Returnera alla rader från en otypad tabell
Följande kod visar hur du hämtar en hel tabell. Eftersom du använder en JSON-tabell kan du selektivt hämta endast några av tabellens kolumner.
public void showAllUntyped(View view) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
final JsonElement result = mJsonToDoTable.execute().get();
final JsonArray results = result.getAsJsonArray();
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.clear();
for (JsonElement item : results) {
String ID = item.getAsJsonObject().getAsJsonPrimitive("id").getAsString();
String mText = item.getAsJsonObject().getAsJsonPrimitive("text").getAsString();
Boolean mComplete = item.getAsJsonObject().getAsJsonPrimitive("complete").getAsBoolean();
ToDoItem mToDoItem = new ToDoItem();
mToDoItem.setId(ID);
mToDoItem.setText(mText);
mToDoItem.setComplete(mComplete);
mAdapter.add(mToDoItem);
}
}
});
} catch (Exception exception) {
createAndShowDialog(exception, "Error");
}
return null;
}
}.execute();
}
Samma uppsättning filtrerings-, filtrerings- och växlingsmetoder som är tillgängliga för den typerade modellen är tillgängliga för den otypade modellen.
Implementera offlinesynkronisering
Azure Mobile Apps Client SDK implementerar även offlinesynkronisering av data med hjälp av en SQLite-databas för att lagra en kopia av serverdata lokalt. Åtgärder som utförs i en offlinetabell kräver inte att mobilanslutningen fungerar. Offlinesynkronisering underlättar motståndskraft och prestanda på bekostnad av mer komplex logik för konfliktlösning. Azure Mobile Apps Client SDK implementerar följande funktioner:
- Inkrementell synkronisering: Endast uppdaterade och nya poster laddas ned, vilket sparar bandbredd och minnesförbrukning.
- Optimistisk samtidighet: Åtgärder antas lyckas. Konfliktlösning skjuts upp tills uppdateringar utförs på servern.
- Konfliktlösning: SDK identifierar när en motstridig ändring har gjorts på servern och tillhandahåller krokar för att varna användaren.
- Mjuk borttagning: Borttagna poster markeras som borttagna, vilket gör att andra enheter kan uppdatera sin offlinecache.
Initiera offlinesynkronisering
Varje offlinetabell måste definieras i offlinecachen innan den används. Normalt görs tabelldefinitionen omedelbart efter att klienten har skapats:
AsyncTask<Void, Void, Void> initializeStore(MobileServiceClient mClient)
throws MobileServiceLocalStoreException, ExecutionException, InterruptedException
{
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
@Override
protected void doInBackground(Void... params) {
try {
MobileServiceSyncContext syncContext = mClient.getSyncContext();
if (syncContext.isInitialized()) {
return null;
}
SQLiteLocalStore localStore = new SQLiteLocalStore(mClient.getContext(), "offlineStore", null, 1);
// Create a table definition. As a best practice, store this with the model definition and return it via
// a static method
Map<String, ColumnDataType> toDoItemDefinition = new HashMap<String, ColumnDataType>();
toDoItemDefinition.put("id", ColumnDataType.String);
toDoItemDefinition.put("complete", ColumnDataType.Boolean);
toDoItemDefinition.put("text", ColumnDataType.String);
toDoItemDefinition.put("version", ColumnDataType.String);
toDoItemDefinition.put("updatedAt", ColumnDataType.DateTimeOffset);
// Now define the table in the local store
localStore.defineTable("ToDoItem", toDoItemDefinition);
// Specify a sync handler for conflict resolution
SimpleSyncHandler handler = new SimpleSyncHandler();
// Initialize the local store
syncContext.initialize(localStore, handler).get();
} catch (final Exception e) {
createAndShowDialogFromTask(e, "Error");
}
return null;
}
};
return runAsyncTask(task);
}
Hämta en referens till offlinecachetabellen
För en onlinetabell använder .getTable()
du . För en offlinetabell använder du .getSyncTable()
:
MobileServiceSyncTable<ToDoItem> mToDoTable = mClient.getSyncTable("ToDoItem", ToDoItem.class);
Alla metoder som är tillgängliga för onlinetabeller (inklusive filtrering, sortering, växling, infogning av data, uppdatering av data och borttagning av data) fungerar lika bra på online- och offlinetabeller.
Synkronisera den lokala offlinecachen
Synkroniseringen ligger inom appens kontroll. Här är ett exempel på en synkroniseringsmetod:
private AsyncTask<Void, Void, Void> sync(MobileServiceClient mClient) {
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
MobileServiceSyncContext syncContext = mClient.getSyncContext();
syncContext.push().get();
mToDoTable.pull(null, "todoitem").get();
} catch (final Exception e) {
createAndShowDialogFromTask(e, "Error");
}
return null;
}
};
return runAsyncTask(task);
}
Om ett frågenamn anges för .pull(query, queryname)
metoden används inkrementell synkronisering för att endast returnera poster som har skapats eller ändrats sedan den senaste hämtningen har slutförts.
Hantera konflikter under offlinesynkronisering
Om en konflikt inträffar under en .push()
åtgärd utlöses en MobileServiceConflictException
. Det servertilldelade objektet är inbäddat i undantaget och kan hämtas med .getItem()
i undantaget. Justera push-överföringen genom att anropa följande objekt i MobileServiceSyncContext-objektet:
.cancelAndDiscardItem()
.cancelAndUpdateItem()
.updateOperationAndItem()
När alla konflikter har markerats som du vill anropar .push()
du igen för att lösa alla konflikter.
Anropa ett anpassat API
Med ett anpassat API kan du definiera anpassade slutpunkter som exponerar serverfunktioner som inte mappas till en infognings-, uppdaterings-, borttagnings- eller läsåtgärd. Genom att använda ett anpassat API kan du ha mer kontroll över meddelanden, inklusive att läsa och ange HTTP-meddelandehuvuden och definiera ett annat meddelandetextformat än JSON.
Från en Android-klient anropar du metoden invokeApi för att anropa den anpassade API-slutpunkten. I följande exempel visas hur du anropar en API-slutpunkt med namnet completeAll, som returnerar en samlingsklass med namnet MarkAllResult.
public void completeItem(View view) {
ListenableFuture<MarkAllResult> result = mClient.invokeApi("completeAll", MarkAllResult.class);
Futures.addCallback(result, new FutureCallback<MarkAllResult>() {
@Override
public void onFailure(Throwable exc) {
createAndShowDialog((Exception) exc, "Error");
}
@Override
public void onSuccess(MarkAllResult result) {
createAndShowDialog(result.getCount() + " item(s) marked as complete.", "Completed Items");
refreshItemsFromTable();
}
});
}
Metoden invokeApi anropas på klienten, som skickar en POST-begäran till det nya anpassade API:et. Resultatet som returneras av det anpassade API:et visas i en meddelandedialogruta, liksom eventuella fel. Med andra versioner av invokeApi kan du skicka ett objekt i begärandetexten, ange HTTP-metoden och skicka frågeparametrar med begäran. Även otypade versioner av invokeApi tillhandahålls.
Lägg till autentisering i appen
Självstudier beskriver redan i detalj hur du lägger till dessa funktioner.
App Service stöder autentisering av appanvändare med hjälp av olika externa identitetsprovidrar: Facebook, Google, Microsoft-konto, Twitter och Azure Active Directory. Du kan ange behörigheter för tabeller för att begränsa åtkomsten för specifika åtgärder till endast autentiserade användare. Du kan också använda identiteten för autentiserade användare för att implementera auktoriseringsregler i serverdelen.
Två autentiseringsflöden stöds: ett serverflöde och ett klientflöde . Serverflödet ger den enklaste autentiseringsupplevelsen eftersom det förlitar sig på identitetsproviderns webbgränssnitt. Inga ytterligare SDK:er krävs för att implementera serverflödesautentisering. Serverflödesautentisering ger ingen djupgående integrering i den mobila enheten och rekommenderas endast för konceptbevisscenarier.
Klientflödet möjliggör djupare integrering med enhetsspecifika funktioner, till exempel enkel inloggning eftersom det förlitar sig på SDK:er som tillhandahålls av identitetsprovidern. Du kan till exempel integrera Facebook SDK i ditt mobilprogram. Mobilklienten byter till Facebook-appen och bekräftar din inloggning innan du byter tillbaka till din mobilapp.
Fyra steg krävs för att aktivera autentisering i din app:
- Registrera din app för autentisering med en identitetsprovider.
- Konfigurera Din App Service-serverdel.
- Begränsa tabellbehörigheter till autentiserade användare endast på App Service-serverdelen.
- Lägg till autentiseringskod i din app.
Du kan ange behörigheter för tabeller för att begränsa åtkomsten för specifika åtgärder till endast autentiserade användare. Du kan också använda SID för en autentiserad användare för att ändra begäranden. Mer information finns i Kom igång med autentisering och Dokumentation om Server SDK HOWTO.
Autentisering: Serverflöde
Följande kod startar en inloggningsprocess för serverflöde med hjälp av Google-providern. Ytterligare konfiguration krävs på grund av säkerhetskrav för Google-providern:
MobileServiceUser user = mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
Lägg dessutom till följande metod i huvudaktivitetsklassen:
// You can choose any unique number here to differentiate auth providers from each other. Note this is the same code at login() and onActivityResult().
public static final int GOOGLE_LOGIN_REQUEST_CODE = 1;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// When request completes
if (resultCode == RESULT_OK) {
// Check the request code matches the one we send in the login request
if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
MobileServiceActivityResult result = mClient.onActivityResult(data);
if (result.isLoggedIn()) {
// login succeeded
createAndShowDialog(String.format("You are now logged in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
createTable();
} else {
// login failed, check the error message
String errorMessage = result.getErrorMessage();
createAndShowDialog(errorMessage, "Error");
}
}
}
}
Den GOOGLE_LOGIN_REQUEST_CODE
som definieras i din huvudsakliga aktivitet används för login()
metoden och i onActivityResult()
metoden. Du kan välja valfritt unikt tal, så länge samma tal används i login()
metoden och onActivityResult()
metoden. Om du abstraherar klientkoden till ett tjänstkort (som visades tidigare) bör du anropa lämpliga metoder på tjänstkortet.
Du måste också konfigurera projektet för anpassade flikar. Ange först en omdirigerings-URL. Lägg till följande kodfragment i AndroidManifest.xml
:
<activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="{url_scheme_of_your_app}" android:host="easyauth.callback"/>
</intent-filter>
</activity>
Lägg till redirectUriScheme i build.gradle
filen för ditt program:
android {
buildTypes {
release {
// … …
manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
}
debug {
// … …
manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
}
}
}
Lägg slutligen till com.android.support:customtabs:28.0.0
i listan med beroenden build.gradle
i filen:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.code.gson:gson:2.3'
implementation 'com.google.guava:guava:18.0'
implementation 'com.android.support:customtabs:28.0.0'
implementation 'com.squareup.okhttp:okhttp:2.5.0'
implementation 'com.microsoft.azure:azure-mobile-android:3.4.0@aar'
implementation 'com.microsoft.azure:azure-notifications-handler:1.0.1@jar'
}
Hämta ID för den inloggade användaren från en MobileServiceUser med metoden getUserId . Ett exempel på hur du använder Futures för att anropa asynkrona inloggnings-API:er finns i Kom igång med autentisering.
Varning
Url-schemat som nämns är skiftlägeskänsligt. Se till att alla förekomster av matchningsfall {url_scheme_of_you_app}
.
Cachelagrar autentiseringstoken
Cachelagring av autentiseringstoken kräver att du lagrar användar-ID och autentiseringstoken lokalt på enheten. Nästa gång appen startar kontrollerar du cacheminnet, och om dessa värden finns kan du hoppa över inloggningsproceduren och extrahera klienten med dessa data. Dessa data är dock känsliga och bör lagras krypterade av säkerhetsskäl om telefonen blir stulen. Du kan se ett fullständigt exempel på hur du cachelagrar autentiseringstoken i avsnittet Cacheautentiseringstoken.
När du försöker använda en token som har upphört att gälla får du ett 401-otillåtet svar. Du kan hantera autentiseringsfel med hjälp av filter. Filtrerar avlyssningsbegäranden till App Service-serverdelen. Filterkoden testar svaret för en 401, utlöser inloggningsprocessen och återupptar sedan begäran som genererade 401.
Använda uppdateringstoken
Token som returneras av Azure App Service-autentisering och auktorisering har en definierad livslängd på en timme. Efter den här perioden måste du autentisera användaren igen. Om du använder en långlivad token som du har fått via klientflödesautentisering kan du autentisera igen med Azure App Service-autentisering och auktorisering med samma token. En annan Azure App Service-token genereras med en ny livslängd.
Du kan också registrera providern för att använda uppdateringstoken. En uppdateringstoken är inte alltid tillgänglig. Ytterligare konfiguration krävs:
För Azure Active Directory konfigurerar du en klienthemlighet för Azure Active Directory-appen. Ange klienthemligheten i Azure App Service när du konfigurerar Azure Active Directory-autentisering. När du anropar
.login()
skickar duresponse_type=code id_token
som en parameter:HashMap<String, String> parameters = new HashMap<String, String>(); parameters.put("response_type", "code id_token"); MobileServiceUser user = mClient.login MobileServiceAuthenticationProvider.AzureActiveDirectory, "{url_scheme_of_your_app}", AAD_LOGIN_REQUEST_CODE, parameters);
För Google skickar du
access_type=offline
som parameter:HashMap<String, String> parameters = new HashMap<String, String>(); parameters.put("access_type", "offline"); MobileServiceUser user = mClient.login MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE, parameters);
För Microsoft-konto väljer du omfånget
wl.offline_access
.
Om du vill uppdatera en token anropar du .refreshUser()
:
MobileServiceUser user = mClient
.refreshUser() // async - returns a ListenableFuture<MobileServiceUser>
.get();
Vi rekommenderar att du skapar ett filter som identifierar ett 401-svar från servern och försöker uppdatera användartoken.
Logga in med klientflödesautentisering
Den allmänna processen för att logga in med klientflödesautentisering är följande:
Konfigurera autentisering och auktorisering för Azure App Service på samma sätt som för serverflödesautentisering.
Integrera autentiseringsproviderns SDK för autentisering för att skapa en åtkomsttoken.
Anropa metoden enligt
.login()
följande (result
ska vara enAuthenticationResult
):JSONObject payload = new JSONObject(); payload.put("access_token", result.getAccessToken()); ListenableFuture<MobileServiceUser> mLogin = mClient.login("{provider}", payload.toString()); Futures.addCallback(mLogin, new FutureCallback<MobileServiceUser>() { @Override public void onFailure(Throwable exc) { exc.printStackTrace(); } @Override public void onSuccess(MobileServiceUser user) { Log.d(TAG, "Login Complete"); } });
Se det fullständiga kodexemplet i nästa avsnitt.
onSuccess()
Ersätt metoden med den kod som du vill använda vid en lyckad inloggning. Strängen {provider}
är en giltig provider: aad (Azure Active Directory), facebook, google, microsoftaccount eller twitter. Om du har implementerat anpassad autentisering kan du också använda taggen anpassad autentiseringsprovider.
Autentisera användare med Active Directory Authentication Library (ADAL)
Du kan använda Active Directory Authentication Library (ADAL) för att logga in användare i ditt program med hjälp av Azure Active Directory. Att använda en klientflödesinloggning är ofta att föredra framför att använda loginAsync()
metoderna eftersom det ger en mer inbyggd UX-känsla och möjliggör ytterligare anpassning.
Konfigurera mobilappens serverdel för AAD-inloggning genom att följa självstudien Konfigurera App Service för Active Directory-inloggning . Slutför det valfria steget för att registrera ett internt klientprogram.
Installera ADAL genom att ändra filen build.gradle så att den innehåller följande definitioner:
repositories { mavenCentral() flatDir { dirs 'libs' } maven { url "YourLocalMavenRepoPath\\.m2\\repository" } } packagingOptions { exclude 'META-INF/MSFTSIG.RSA' exclude 'META-INF/MSFTSIG.SF' } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation('com.microsoft.aad:adal:1.16.1') { exclude group: 'com.android.support' } // Recent version is 1.16.1 implementation 'com.android.support:support-v4:28.0.0' }
Lägg till följande kod i programmet och gör följande ersättningar:
- Ersätt INSERT-AUTHORITY-HERE med namnet på den klientorganisation där du etablerade programmet. Formatet ska vara https://login.microsoftonline.com/contoso.onmicrosoft.com.
- Ersätt INSERT-RESOURCE-ID-HERE med klient-ID:t för mobilappens serverdel. Du kan hämta klient-ID:t från fliken Avancerat under Azure Active Directory-inställningar i portalen.
- Ersätt INSERT-CLIENT-ID-HERE med det klient-ID som du kopierade från det interna klientprogrammet.
- Ersätt INSERT-REDIRECT-URI-HERE med webbplatsens slutpunkt /.auth/login/done med hjälp av HTTPS-schemat. Det här värdet bör likna https://contoso.azurewebsites.net/.auth/login/done.
private AuthenticationContext mContext;
private void authenticate() {
String authority = "INSERT-AUTHORITY-HERE";
String resourceId = "INSERT-RESOURCE-ID-HERE";
String clientId = "INSERT-CLIENT-ID-HERE";
String redirectUri = "INSERT-REDIRECT-URI-HERE";
try {
mContext = new AuthenticationContext(this, authority, true);
mContext.acquireToken(this, resourceId, clientId, redirectUri, PromptBehavior.Auto, "", callback);
} catch (Exception exc) {
exc.printStackTrace();
}
}
private AuthenticationCallback<AuthenticationResult> callback = new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onError(Exception exc) {
if (exc instanceof AuthenticationException) {
Log.d(TAG, "Cancelled");
} else {
Log.d(TAG, "Authentication error:" + exc.getMessage());
}
}
@Override
public void onSuccess(AuthenticationResult result) {
if (result == null || result.getAccessToken() == null
|| result.getAccessToken().isEmpty()) {
Log.d(TAG, "Token is empty");
} else {
try {
JSONObject payload = new JSONObject();
payload.put("access_token", result.getAccessToken());
ListenableFuture<MobileServiceUser> mLogin = mClient.login("aad", payload.toString());
Futures.addCallback(mLogin, new FutureCallback<MobileServiceUser>() {
@Override
public void onFailure(Throwable exc) {
exc.printStackTrace();
}
@Override
public void onSuccess(MobileServiceUser user) {
Log.d(TAG, "Login Complete");
}
});
}
catch (Exception exc){
Log.d(TAG, "Authentication error:" + exc.getMessage());
}
}
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (mContext != null) {
mContext.onActivityResult(requestCode, resultCode, data);
}
}
Justera kommunikationen mellan klient och server
Klientanslutningen är normalt en grundläggande HTTP-anslutning med det underliggande HTTP-biblioteket som medföljer Android SDK. Det finns flera orsaker till att du vill ändra på det:
- Du vill använda ett alternativt HTTP-bibliotek för att justera tidsgränser.
- Du vill ange en förloppsindikator.
- Du vill lägga till en anpassad rubrik för att stödja API-hanteringsfunktioner.
- Du vill fånga upp ett misslyckat svar så att du kan implementera omautentisering.
- Du vill logga serverdelsbegäranden till en analystjänst.
Använda ett alternativt HTTP-bibliotek
.setAndroidHttpClientFactory()
Anropa metoden omedelbart efter att du har skapat klientreferensen. Om du till exempel vill ange tidsgränsen för anslutningen till 60 sekunder (i stället för standardvärdet 10 sekunder):
mClient = new MobileServiceClient("https://myappname.azurewebsites.net");
mClient.setAndroidHttpClientFactory(new OkHttpClientFactory() {
@Override
public OkHttpClient createOkHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setReadTimeout(60, TimeUnit.SECONDS);
client.setWriteTimeout(60, TimeUnit.SECONDS);
return client;
}
});
Implementera ett förloppsfilter
Du kan implementera en avlyssning av varje begäran genom att implementera en ServiceFilter
. Följande uppdaterar till exempel ett fördefinierad förloppsfält:
private class ProgressFilter implements ServiceFilter {
@Override
public ListenableFuture<ServiceFilterResponse> handleRequest(ServiceFilterRequest request, NextServiceFilterCallback next) {
final SettableFuture<ServiceFilterResponse> resultFuture = SettableFuture.create();
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mProgressBar != null) mProgressBar.setVisibility(ProgressBar.VISIBLE);
}
});
ListenableFuture<ServiceFilterResponse> future = next.onNext(request);
Futures.addCallback(future, new FutureCallback<ServiceFilterResponse>() {
@Override
public void onFailure(Throwable e) {
resultFuture.setException(e);
}
@Override
public void onSuccess(ServiceFilterResponse response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mProgressBar != null)
mProgressBar.setVisibility(ProgressBar.GONE);
}
});
resultFuture.set(response);
}
});
return resultFuture;
}
}
Du kan koppla det här filtret till klienten på följande sätt:
mClient = new MobileServiceClient(applicationUrl).withFilter(new ProgressFilter());
Anpassa begärandehuvuden
Använd följande ServiceFilter
och bifoga filtret på samma sätt som ProgressFilter
:
private class CustomHeaderFilter implements ServiceFilter {
@Override
public ListenableFuture<ServiceFilterResponse> handleRequest(ServiceFilterRequest request, NextServiceFilterCallback next) {
runOnUiThread(new Runnable() {
@Override
public void run() {
request.addHeader("X-APIM-Router", "mobileBackend");
}
});
SettableFuture<ServiceFilterResponse> result = SettableFuture.create();
try {
ServiceFilterResponse response = next.onNext(request).get();
result.set(response);
} catch (Exception exc) {
result.setException(exc);
}
}
}
Konfigurera automatisk serialisering
Du kan ange en konverteringsstrategi som gäller för varje kolumn med hjälp av gson-API:et. Android-klientbiblioteket använder gson i bakgrunden för att serialisera Java-objekt till JSON-data innan data skickas till Azure App Service. Följande kod använder metoden setFieldNamingStrategy() för att ange strategin. Det här exemplet tar bort det första tecknet (ett "m") och sedan gemener nästa tecken för varje fältnamn. Det skulle till exempel förvandla "mId" till "id". Implementera en konverteringsstrategi för SerializedName()
att minska behovet av anteckningar på de flesta fält.
FieldNamingStrategy namingStrategy = new FieldNamingStrategy() {
public String translateName(File field) {
String name = field.getName();
return Character.toLowerCase(name.charAt(1)) + name.substring(2);
}
}
client.setGsonBuilder(
MobileServiceClient
.createMobileServiceGsonBuilder()
.setFieldNamingStrategy(namingStrategy)
);
Den här koden måste köras innan du skapar en mobil klientreferens med hjälp av MobileServiceClient.