65.9K
CodeProject 正在变化。 阅读更多。
Home

在后端即服务 (BaaS) 平台上开发移动应用程序

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2015年7月2日

CPOL

6分钟阅读

viewsIcon

13382

比较 Firebase 和 SynergyKit 在开发聊天应用程序时的异同

引言

如今,实时应用程序变得越来越受欢迎,但这类应用程序的开发并非易事。这也是为什么新的实时平台不断涌现的原因。它们将使实时应用程序的实现更加容易。开发人员不再需要担心与服务器的数据同步,而且他们可以节省高达 80% 的产品开发时间,并将更多精力投入到 UX/UI 上。


世界上最著名的实时平台很可能是 Firebase,截至今日,其注册用户已超过 200,000。另一方面,SynergyKit 是捷克公司 Letsgood.com(Etnetera Group)新开发平台的名称。目前 SynergyKit 处于公测阶段。

SynergyKit 还是 Firebase?

为了比较这两种产品,我将以一个非常常见的用例——聊天应用程序的一部分——为例。该应用程序会实时显示用户消息,当应用程序不在前台时,会通过推送通知发送。您可以通过 Facebook 个人资料进行注册和登录。


包含源代码的示例应用程序可在 GitHub 上找到。

应用程序截图

应用程序的外观基于 Synergit 的示例应用程序,并略有修改。

安装

SynergyKit

SynergyKit SDK for Android 的最低要求是 Android SDK 14 版本。

需要在 build.gradle 文件中的 dependencies 元素下添加以下依赖项。

dependencies {
   ...
   compile 'com.letsgood:synergykit-sdk-android:2.1.7'
}

由于应用程序使用互联网访问,因此有必要向 Android 请求使用互联网的权限。这可以在 AndroidManifest.xml 文件中完成,您需要在 manifest 元素中添加以下代码。

<manifest ... >
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>

接下来,您需要在首次使用前初始化 SynergyKit SDK。我建议在 Application 类的 onCreate 方法中进行。

public void onCreate() {
   super.onCreate();

   Synergykit.init(APPLICATION_TENANT, APPLICATION_KEY);
   ...
}

Firebase

Firebase SDK for Android 的最低要求是 Android SDK 10 版本。

需要在 build.gradle 文件中添加以下依赖项和 packagingOptions。

android {
   ...
   packagingOptions {
      exclude 'META-INF/LICENSE'
      exclude 'META-INF/LICENSE-FIREBASE.txt'
      exclude 'META-INF/NOTICE'
   }
}
dependencies {
   ...
   compile 'com.firebase:firebase-client-android:2.3.0'
}

由于应用程序使用互联网访问,因此有必要向 Android 请求使用互联网的权限。这可以在 AndroidManifest.xml 文件中完成,您需要将此代码插入 manifest 元素。

<manifest ... >
   <uses-permission android:name="android.permission.INTERNET" />
   ...
</manifest>

在首次使用之前,Firebase 需要 Context 才能运行,我建议在 Application 类的 onCreate 方法中进行。

public void onCreate() {
   super.onCreate();

   Firebase.setAndroidContext(this);
   ...
}

用户登录

用户将通过 Facebook 登录,Facebook 提供的姓名将被保存并用于发送消息。将为每个用户保存其在线状态信息。

SynergyKit

SDK 不支持从 Facebook AccessToken 获取姓名,因此您需要在登录前获取该姓名。这可以通过 GraphRequest 完成。用户的姓名将保存在 Name 变量中。

GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
   @Override
   public void onCompleted(JSONObject object, GraphResponse response) {
      String name = null;
      try {
         name = object.getString("name"); // user's name on Facebook
      } catch (JSONException e) {
         e.printStackTrace();
      }
   }
});
Bundle parameters = new Bundle();
parameters.putString("fields", "name");
request.setParameters(parameters);
request.executeAsync();

在 User 参数中将传递 SynergyKitUser,其中将设置姓名、在线状态,并将保存数据。

Synergykit.linkFacebook(user, synergykitFacebookAuthData, new UserResponseListener() {
   @Override
   public void doneCallback(int statusCode, SynergykitUser user) {
      // login successful
   }
   @Override
   public void errorCallback(int statusCode, SynergykitError errorObject) {
      // login error
   }
});

Firebase

通过 Firebase 登录更简单。您无需通过 GraphRequest 获取用户姓名。Firebase SDK for Android 会自行解决这个问题。

private Firebase firebase;
...
firebase = new Firebase("https://<APP_URL>.firebaseio.com"); // onCreate init
...
firebase.authWithOAuthToken("facebook", accessToken.getToken(), new Firebase.AuthResultHandler() {
   @Override
   public void onAuthenticated(AuthData authData) {
      // login successful
      setOnline(true); // my method described below
   }
   @Override
   public void onAuthenticationError(FirebaseError firebaseError) {
      // login error
   }
});

但这只是用户登录,而不是保存用户。要保存用户,我将使用一个在服务器上更改用户在线状态的函数。该函数在下面的“在线状态设置”部分进行说明。

在线状态设置

显示聊天界面的用户处于在线状态。当应用程序被另一个应用程序覆盖、显示关闭或用户关闭应用程序时,它将切换到离线状态。这些函数会调用 onResume 和 onPause,因此它们会设置正确的状态。 

SynergyKit

下面描述的函数将用户的在线状态设置为“在线”。参数 online 是用户的状态。第二个参数 paralleMode 将导致此操作异步运行。

private void setOnline(boolean online, boolean parallelMode) {
   if (user == null) return;
   user.setOnline(online);
   Synergykit.updateUser(user, new UserResponseListener() {
      @Override
      public void doneCallback(int statusCode, SynergykitUser synergykitUser) {
         user = (SKUser) synergykitUser; // user successfully updated
      }
      @Override
      public void errorCallback(int statusCode, SynergykitError synergykitError) {
         // user update failed
      }
   }, parallelMode);
}

Firebase

下面描述的函数将用户的在线状态设置为“在线”。如果用户不存在,则会创建用户。Firebase 使用 JSON 数据,因此这里使用了 map。

private void setOnline(boolean online) {
   Map<String, Object> map = new HashMap<>();
   map.put("name", userName); // user's name
   map.put("online", online); // online status
   firebaseUsers.child("" + uId).setValue(map); // create or override previous values
}

消息传递

消息传递通过将消息添加到两个平台的集合来解决,应用程序会侦听通过 websocket 接收到的更改。此集合会自动侦听新消息。

SynergyKit

创建了一个包含所有必要属性的类,并为了 SynergyKit 的需求而扩展了 SynergykitObject。以下代码会将一条消息添加到集合中。

Synergykit.createRecord(COLLECTION_MESSAGES, message, new ResponseListener() {
   @Override
   public void doneCallback(int statusCode, SynergykitObject synergykitObject) {
      // message sent
   }
   @Override
   public void errorCallback(int statusCode, SynergykitError synergykitError) {
      // sending message failed
   }
}, true);

Firebase

创建了一个包含所有必要属性的类。以下代码会将一条消息添加到集合中。

firebaseMessages.push().setValue(message, new Firebase.CompletionListener() {
   @Override
   public void onComplete(FirebaseError firebaseError, Firebase firebase) {
      if (firebaseError != null) {
         // sending message failed
      } else {
         // message sent
      }
   }
});

接收消息

两个平台的接收消息都是通过侦听添加到集合的事件来解决的。应用程序将显示最后 100 条消息。

SynergyKit

以下代码从 messages 集合中获取最后 100 条记录。

SynergykitUri synergyKitUri = UriBuilder.newInstance()
 .setResource(Resource.RESOURCE_DATA) // setting resource to data
 .setCollection(COLLECTION_MESSAGES) // setting collection to messages
 .setOrderByDesc("createdAt") // sorting by "createdAt"
 .setTop(prevMessageCount) // top 100 messages
 .build();
SynergykitConfig config = SynergykitConfig.newInstance()
 .setParallelMode(true)
 .setType(SKMessage[].class) // setting result type
 .setUri(synergyKitUri); // setting URI created above
Synergykit.getRecords(config, new RecordsResponseListener() {
   @Override
   public void doneCallback(int statusCode, SynergykitObject[] synergykitObjects) {
      SKMessage[] messages = (SKMessage[]) synergykitObjects; // posledních 100 zpráv sestupně
   }
   @Override
   public void errorCallback(int statusCode, SynergykitError synergykitError) {}
});

以下代码将注册一个套接字以侦听 created 事件。

// listening on socket for event created in collection messages
Synergykit.onSocket(EVENT_CREATED, COLLECTION_MESSAGES, new SocketEventListener() {
   @Override
   public void call(Object... objects) { 
      String data = objects[0].toString(); // JSON data
      final SKMessage message = GsonWrapper.getGson().fromJson(data, SKMessage.class); // get message
   }
   @Override
   public void subscribed() {}
   @Override
   public void unsubscribed() {}
});

Synergykit.connectSocket();

Firebase

Query 用于过滤和减少消息数量。ChildEventListener 允许侦听更改。

Query query = firebaseMessages.orderByChild("timestamp").limitToLast(prevMessageCount);
query.addChildEventListener(new ChildEventListener() {
   @Override
   public void onChildAdded(DataSnapshot dataSnapshot, String s) {
      if (dataSnapshot == null) return; // no data received
      FBMessage message = dataSnapshot.getValue(FBMessage.class); // get message
   }

   @Override
   public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
   @Override
   public void onChildRemoved(DataSnapshot dataSnapshot) {}
   @Override
   public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
   @Override
   public void onCancelled(FirebaseError firebaseError) {}
});

推送通知

当用户不在聊天屏幕时,将接收并显示推送通知。推送通知的形式为“发送者:消息”,并在接收时播放默认通知声音。有关 GCM 的推送通知信息。

SynergyKit

前提是已在 Google Console 中创建了应用程序。在 SynergyKit 的应用程序设置中,有必要输入所谓的 GCM API 密钥,这可以在“设置 -> Android GCM”选项卡中完成。

必须将新的依赖项添加到 build.gradle 文件中。

dependencies {
   ...
   compile 'com.google.android.gms:play-services-gcm:7.5.0'
}

注册 ID 是通过向 GCM 服务注册获得的。

regid = gcm.register(SENDER_ID);

先前获得的注册 ID 必须保存在将发送推送通知的服务器上。SynergyKit 将此信息保存在 SynergyKitPlatform 类的实例中。SynergyKitPlatform 类是 SynergykitUser 类或其子类的组成部分。

if (platform == null) { // create new platform
   SynergykitPlatform platform = new SynergykitPlatform(regid); // passing gcm registration id
   Synergykit.addPlatform(platform, new PlatformResponseListener() {
      @Override
      public void doneCallback(int statusCode, SynergykitPlatform platform) {
         // add successful
      }
      @Override
      public void errorCallback(int statusCode, SynergykitError errorObject) {
         // add failed
      }
   }, true);
} else if (!platform.getRegistrationId().equals(regid)) { // id is different
   platform.setRegistrationId(regid);
   Synergykit.updatePlatform(platform, null, true); // update platform without listener
}

Cloud Code 允许在服务器端运行代码。可以从设备中启用或在集合事件发生时自动启用。代码是用 JavaScript 编写的,可在浏览器 IDE 中编写,也可以在那里进行调试。

我已将触发器设置为 messages 集合中的“created”事件,因此在收到消息后将调用 Cloud Code。以下 Cloud Code 会获取所有在线属性设置为 false 的用户,并将向他们发送通知。

var queryOfflineUsers = Synergykit.Query(Synergykit.User()); // begin query
// gets all users with online state set to false
queryOfflineUsers.where().attribute("online").isEqualTo(false).find({
   success: function(offline_users, code) {
      if (code == 200) {
         var notification = Synergykit.Notification(offline_users); // creating notification with all offline users
         var text = parameters.name + ': ' + parameters.text; // ziskani textu notifikace
         notification.set("alert", text); // pridani textu k notifikaci
         notification.send({ // odeslani notifikace
            success: function(result, statusCode) {
               callback({
                  result: 'success',
                  offline_users: offline_users
               });
            },
            error: function(error, statusCode) {
               callback;
            }
         });
      } else {
         callback;
      }
   },
   error: callback
});

通知已发送给所有用户,但应用程序尚未接收到。需要在 Android 中实现 GCM 通知接收。

通过以下代码,我在 manifest 中请求了相关权限。

<manifest ... >
   <uses-permission android:name="android.permission.GET_ACCOUNTS" />
   <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
   <uses-permission android:name="android.permission.WAKE_LOCK" />
   <permission
      android:name="<PACKAGE_NAME>.permission.C2D_MESSAGE"
      android:protectionLevel="signature" />
   <uses-permission android:name="<PACKAGE_NAME>.permission.C2D_MESSAGE" />
</manifest>

GcmReceiver 接收来自 GCM 的消息,并必须添加到 manifest 中。

<manifest ... >
   <application ... >
      ...
      <receiver
         android:name="com.google.android.gms.gcm.GcmReceiver"
         android:exported="true"
         android:permission="com.google.android.c2dm.permission.SEND">
         <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
         </intent-filter>
      </receiver>
      ...
   </application>
</manifest>

MyGcmListenerService 是一个接收来自 GCMReceiver 的消息并随后创建通知的服务。该服务也必须添加到 manifest 中。

<manifest ... >
   <application ... >
      ...
      <service
         android:name="<PACKAGE_NAME>.MyGcmListenerService"
         android:exported="false">
         <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
         </intent-filter>
      </service>
      ...
   </application>
</manifest>

MyGcmListenerService 类在用户接受通知时向用户显示通知,这些通知来自 GcmReceiver。

public class MyGcmListenerService extends GcmListenerService {
   @Override
   public void onMessageReceived(String from, Bundle data) {
      String message = data.getString("alert"); // get text of message
      sendNotification(message);
   }
   private void sendNotification(String message) {
      NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
      ... // setup notification
      NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
      notificationManager.notify(0 /* notification ID */, notificationBuilder.build());
   }
}

Firebase

Firebase 不支持发送推送通知,其实现并不容易。尽管如此,互联网上有很多教程可以帮助您自行解决此问题,并构建自己的服务器应用程序。

结论

对于此特定应用程序,使用 SynergyKit 更好。首先,要在 Firebase 平台上创建推送通知,您需要使用第三方产品。其次,SynergyKit 允许将部分代码移到服务器,从而延长设备的续航时间。服务器部分可以在浏览器中进行修改,这些更改不需要更新应用程序。两个平台都提供简单的用户登录、读写数据功能。

© . All rights reserved.