Android GCM 中通知生成问题

3

我有以下两个问题:

第一个问题:

我必须为使用同一设备的两个客户注册,因此它们具有相同的注册ID。

当我从服务器端向这两个客户发送优惠时,显示的通知应该取决于已登录的客户。

例如(见图片):

enter image description here enter image description here 在我的应用程序中,我有一个客户登录表单。在这个表单中,如果用户gnanavel登录,应用程序必须只接收他的优惠,而不是其他人的优惠。

同样,如果用户jeya登录,应用程序必须只接收她的优惠,而不是其他人的优惠。

目前应用程序正在接收两种优惠。

编辑:

我在我的数据库中创建了登录状态字段。如果我的客户在设备上登录,那么它只会收到他的优惠通知,而不是其他人的。这很好地工作。

我在点击优惠按钮时检查条件:

 $getregid = mysqli_query($con,"select * from pim_customers where customer_id='$customer_id' and gcm_regid='$regId' and loginstatus='Y'");

我编写了这些条件,意味着我的第一个问题已经解决。但是另一个问题出现了。 另一个问题是:
当管理员输入一些优惠信息时,只有当客户登录时才能在设备上收到通知。否则就不应该收到通知。这部分工作正常。
问题在于,当我的客户长时间未登录并且在此期间管理员输入了更多的优惠信息时。
如果客户在2天后登录应用程序,则应收到所有待处理消息。我如何获取待处理消息?
当管理员输入优惠时,如果客户已经注销,那么数据库中的登录状态为“N”。那么我该如何执行这些条件并接收通知呢?
 $getregid = mysqli_query($con,"select * from pim_customers where customer_id='$customer_id' and gcm_regid='$regId' and loginstatus='Y'");

当点击“offer”按钮时,这是我执行的服务器端代码:

if (isset($_GET["regId"]) && isset($_GET["customer_id"]) && isset($_GET["message"])) {
  $regId = $_GET["regId"];
  $message = $_GET["message"];
  $customer_id = $_GET["customer_id"];
  include_once './GCM.php';
  $getregid = mysqli_query($con,"select * from pim_customers where customer_id='$customer_id' and gcm_regid='$regId' and loginstatus='Y'");
  $count1=mysqli_num_rows($getregid);
  while($row = mysqli_fetch_array($getregid))
  {
    $id=$row['customer_id'];
  }
  if (mysqli_num_rows($getregid) > 0) {
    $query = mysqli_query($con,"select count(offer) as count from pim_productdeal where customer_id='$id' and offer!=''");
    $count = mysqli_fetch_array($query);
    $msg = $count['count'];
    $gcm = new GCM();
    $registatoin_ids = array($regId);
    $message = array("price" => $msg." "."The offers received");
    $result = $gcm->send_notification($registatoin_ids, $customer_id, $message);
    echo $result;
  }
}

这是我的Android端代码:
public class GCMIntentService extends GCMBaseIntentService {

  private static final String TAG = "GCMIntentService";
  String regId;

  public GCMIntentService() {
    super(SENDER_ID);
  }

  @Override
  protected void onRegistered(Context context, String registrationId) {
    ServerUtilities.register(context, RegisterActivity.first_name, RegisterActivity.last_name, RegisterActivity.email, RegisterActivity.password, registrationId);
  }

  @Override
  protected void onUnregistered(Context context, String registrationId) {
    Log.i(TAG, "Device unregistered");
    displayMessage(context, getString(R.string.gcm_unregistered));
    ServerUtilities.unregister(context, registrationId);
  }

  @Override
  protected void onMessage(Context context, Intent intent) {
    Log.i(TAG, "Received message");
    GCMRegistrar.checkDevice(this);
    GCMRegistrar.checkManifest(this);
    regId = GCMRegistrar.getRegistrationId(this);
    String message = intent.getExtras().getString("price");
    displayMessage(context, message);
    if(Constants.response != null) {
      generateNotification(context,message);
    }
  }

  @Override
  protected void onDeletedMessages(Context context, int total) {
    Log.i(TAG, "Received deleted messages notification");
    String message = getString(R.string.gcm_deleted, total);
    displayMessage(context, message);
    // notifies user
    generateNotification(context,message);
  }

  @Override
  public void onError(Context context, String errorId) {
    Log.i(TAG, "Received error: " + errorId);
    displayMessage(context, getString(R.string.gcm_error, errorId));
  }

  @Override
  protected boolean onRecoverableError(Context context, String errorId) {
    // log message
    Log.i(TAG, "Received recoverable error: " + errorId);
    displayMessage(context, getString(R.string.gcm_recoverable_error,
            errorId));
    return super.onRecoverableError(context, errorId);
  }

  private static void generateNotification(Context context,String message) {
    int icon = R.drawable.icon;
    long when = System.currentTimeMillis();
    NotificationManager notificationManager = (NotificationManager)
            context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = new Notification(icon, message, when);

    String title = context.getString(R.string.app_name);

    Intent notificationIntent = new Intent(context, MyDealProducts.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
            Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent intent =
            PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, title, message, intent);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.defaults |= Notification.DEFAULT_SOUND;
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notificationManager.notify(0, notification);      
  }
}
3个回答

5

我修改了你的问题,使它更容易理解。希望我没有改变你的意思。如果我有误,请你指出来。

现在回答你的问题:

  1. 你的服务器应该知道哪个用户当前登录到了哪个设备上。你需要在服务器上维护一个已登录用户的表,对于每个已登录用户,表中会保存他/她登录的设备标识符。为了做到这一点,每当用户登录或退出登录时,你需要向服务器发送一个请求。该请求应包含用户ID和设备ID。对于设备ID,你可以使用注册ID,也可以使用服务器生成的其他ID(最好生成一个比注册ID更短的ID,以便更高效地使用)。你需要维护一个将注册ID映射到设备ID的表。

  2. 当管理员创建一个新的报价并分配给某个用户时,只有当该用户已登录时,你才会向应用程序发送GCM通知。因此,在两个用户使用同一设备的情况下,如果其中一个用户已登录,则仅向该设备发送一条通知。如果两个用户都没有登录,则不会发送任何通知。你将新的报价存储在数据库中,并等待其中一个用户登录。

  3. 当GCM消息到达设备时,你需要确保它是针对当前已登录的用户的,因为有可能在消息被发送后,一个用户退出登录,但另一个用户在它到达设备之前登录。为此,你的GCM消息应该包含用户标识符作为附加字段。如果某条消息到达设备并且其用户ID与当前已登录的用户不匹配,则舍弃该消息并不显示通知。

  4. 当用户登录时,服务器将收到一个请求(参见#1)。在该请求的响应中,服务器应该向设备返回用户在服务器数据库中所拥有的所有报价。

  5. 对于长时间处于非活动状态的设备而言,在设备再次变为活动状态时,旧的消息可能会从GCM中发送到它(如果它们尚未被GCM舍弃)。如果这些消息不属于当前已登录的用户,则舍弃它们(参见#3)。如果它们属于当前已登录的用户,则应该显示它们。

  6. 我不了解PHP,但根据我对你服务器代码的有限理解,似乎你向设备发送一个包含用户所拥有的报价数量的GCM消息。你应该为你发送的所有消息使用相同的collapse_key。这样,如果设备处于离线状态时,服务器发送了多条消息,那么当设备再次变为活动状态时,只有其中一条消息会被发送到设备上。如果所有待处理消息只包含可用报价的数量,那么你不需要获取所有这些消息。


请查看我编辑过的问题并给我解决方案,谢谢编辑和提供好的答案。但是我又提出了另一个问题。 - user2218667
@user2218667 不客气。我已经解决了你的第二个问题。当顾客在长时间(比如2天)之后登录时,你不应该使用GCM来向顾客发送优惠。当顾客登录时,应用程序已经在运行,所以应用程序可以请求服务器发送给它该顾客拥有的所有优惠。然后,应用程序可以按照你的要求显示这些优惠。 - Eran

0

在从您的服务器发送消息时,无需设置time_to_live。根据文档默认的存活时间为4周

另外,请确保在用户注销时不要注销设备。


这里我没有提到 TTL。同时,如果我的客户注销,则设备 ID 仍然可用。 - user2218667

0
当您从服务器发送推送通知时,请添加一个Notification_id字段。现在,在移动端使用本地数据库(SQLite)来管理已显示给用户的通知 ID。
当应用程序启动时,您需要实现对您的Web服务器进行调用以获取当前所有通知列表。这样,可以将来自服务器的通知 ID 与本地通知 ID 匹配。然后,您可以提取那些不在您的数据库中的特定通知的详细信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接