[英]Call Firebase database from Google App Engine
我按照本教程設置了我的Google App Engine實例,我也在使用Firebase。 我的目標是將所有“計算”放在Google App Engine上。 我想調用下面這樣的函數:
MyEndpoint:
package productions.widowmaker110.backend;
/** An endpoint class we are exposing */
@Api(
name = "myApi",
version = "v1",
namespace = @ApiNamespace(
ownerDomain = "backend.widowmaker110.productions",
ownerName = "backend.widowmaker110.productions",
packagePath=""
)
)
public class MyEndpoint {
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String value = dataSnapshot.getValue(String.class);
Log.d(TAG, "Value is: " + value);
}
@Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
MyBean response = new MyBean();
response.setData("Hi, " + name);
return response;
}
}
主要活動:
package productions.widowmaker110.gpsweather;
// imports...
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new EndpointsAsyncTask().execute(new Pair<Context, String>(this, "Manfred"));
}
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private MyApi myApiService = null;
private Context context;
@Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
}
我了解Firebase的上述代碼是特定於Android的,因此在Google App Engine實例上運行不起作用。 我想知道是否有人知道如何從Google App Engine后端對firebase數據庫執行CRUD操作。 任何幫助表示贊賞。
您需要使用Firebase Server SDK進行服務器端調用。 您可以在此處找到有關設置和使用它的信息:
將Firebase與Google Cloud Endpoints一起使用時,請注意您需要將Firebase方法與Tasks API結合使用。 由於Firebase方法沒有阻止,如果您不使用任務,則在您對Firebase進行的呼叫有機會返回其結果之前,您的端點將返回。 有關使用任務的簡要介紹,請查看以下鏈接。 這是在Google I / O 2016上發表的演講。演講者正在討論Android上的任務和Firebase,但在服務器上使用Tasks和Firebase時的概念是相同的。 請注意,他們已將Tasks API與Firebase Server SDK一起包含在內。 我已經跳過直接涉及任務的談話部分。
適用於Android的Firebase SDK:深入了解技術
以下示例是您需要在Endpoint返回值之前處理Firebase讀/寫操作的結果,或者其他代碼是否依賴於Firebase讀/寫操作的結果。 這些是服務器端示例。 我將假設你關心寫操作是否成功。 可能有更好的方法來執行這些服務器端操作,但這是我到目前為止所做的。
使用setValue()進行示例寫入操作:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
YourModelClass obj = new YourModelClass();
當調用setValue()
方法時,它返回一個Task
對象,保持對它的引用。
Task<Void> setValueTask = ref.setValue(obj);
創建TaskCompletionSource
對象。 應使用您選擇的結果類型對此對象進行參數化。 我將使用Boolean
作為此示例的結果類型。
final TaskCompletionSource<Boolean> tcs = new TaskCompletionSource<>();
產生Task
從TaskCompletionSource
將在步驟2中創建同樣,將所生成的Task
應該使用相同的參數類型作為TaskCompletionSource
對象。
Task<Boolean> tcsTask = tcs.getTask();
將完成偵聽器添加到由setValue()
調用生成的Task
。 在完成偵聽器中,在步驟3中創建的Task
上設置適當的結果。在TaskCompletionSouce
對象上調用setResult()
將從其創建的Task
標記為完成。 這對第5步很重要。
setValueTask.addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if(task.isSuccessful()){ tcs.setResult(true); }else{ tcs.setResult(false); } } });
調用Task.await()
來阻止當前線程,直到您感興趣的Task
完成。 我們正在等待TaskCompletionSource
對象生成的Task
被標記為complete。 當我們在用於生成Task
的TaskCompletionSource
上調用setResult()
時,我們將認為此Task
已完成,就像我們在步驟4中所做的那樣。一旦完成,它將返回結果。
try { Boolean result = Tasks.await(tcsTask); }catch(ExecutionException e){ //handle exception }catch (InterruptedException e){ //handle exception }
就是這樣,當前線程將阻塞,直到Tasks.await()
返回一個值。 如果要保持當前線程無限期地被阻止,您還可以(並且應該)在Tasks.await()
方法上設置超時值。
如果您只對setValue()
生成的Task
是否已完成並且不關心它是否成功感興趣,那么您可以跳過TaskCompletionSource
的創建並直接在該Task
上使用Tasks.await()
。 這同樣適用於updateChildren()
。 如果您願意,可以使用updateChilden()
或setValue()
的方法調用,它使用DatabaseReference.CompletionListener
和TaskCompletionListener。
等待讀取操作完成是類似的。
使用addListenerForSingleValueEvent()進行示例讀取操作
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
YourModelClass mModelClassObject;
創建一個TaskCompletionSource
對象,該對象使用您希望從其生成的Task
所期望的結果進行參數化。
final TaskCompletionSource<YourModelClass> tcs = new TaskCompletionSource<>();
從TaskCompletionSource
對象生成Task
Task<YourModelClass> tcsTask = tcs.getTask();
在我們的DatabaseReference
上調用addListenerForSingleValueEvent()
並在步驟2中生成的Task
上調用setResult()
。
ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { YourModelClass result = dataSnapshot.getValue(YourModelClass.class); if(result != null){ tcs.setResult(result); } } @Override public void onCancelled(DatabaseError databaseError){ //handle error } });
調用Tasks.await()
來阻止當前線程,直到您感興趣的Task
完成。 當我們調用setResult()
時, Task
將被視為完成,就像我們在步驟3中所做的那樣,並將返回結果。
try { mModelClassObject = Tasks.await(tcsTask); }catch(ExecutionException e){ //handle exception }catch (InterruptedException e){ //handle exception }
如上所述,您可以使用Tasks.await()
方法以及超時值來防止當前線程無限期地被阻止。
就像抬頭一樣,我發現Firebase不會殺死用於其操作的后台線程。 這意味着GAE實例永遠不會空閑。 查看此主題以獲取更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.