2 Android 应用之间通过 GCM 的通信

Communication between 2 Android apps over GCM

我在两台不同的设备上有 2 个 Android 应用程序。 App 1 是固定的,app 2 是移动的。我希望应用程序 1 找到最近的应用程序 2 设备并像 snapchat 一样进行通信,但我想用应用程序 2 的当前位置更新应用程序 1。我将应用程序 1 的位置存储在服务器中并检索应用程序 2 的位置并计算它们之间的距离,然后通过 GCM 将应用程序 1 的位置发送到应用程序 2。但事实证明这比我原先想象的要复杂。我还尝试将移动应用程序的位置存储在数据库中,并在固定请求通信时获取更新的位置,但这意味着数据库更新太多。有人可以提示我如何高效地完成这项工作吗?以下是计算它们之间的距离和发送位置的代码片段。

function distance_slc($lat1, $lon1, $lat2, $lon2) {
    global $earth_radius;
    global $delta_lat;
    global $delta_lon;
    $distance = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($delta_lon));
    $distance = acos($distance);
    $distance = rad2deg($distance);
    $distance = $distance * 60 * 1.1515;
    $distance = round($distance, 4);

    return $distance;
}


        function compute($id, $lat, $lon) {
        $p = getPLocation(); 
        $d = array($id, $lat, $lon);  

        foreach ($d as $index => $value) {
        $d_pass_distance = distance_slc($p['latitude'], $p['longitude'], $d['1'], $d['2']);

        $closest_d = 0;
        if ($closest_d = min($d_pass_distance)) {

            sendPLocation($d['0'], $p['latitude'], $p['longitude']);
        }
    }
}

function sendUserLocation($id, $lat, $lon) {
//request url
        //$url = 'https://android.googleapis.com/gcm/send';
        $url = 'gcm-preprod.googleapis.com:5236';   //this url is only for testing not production
//your api key
        $apiKey = 'myserverapikeyhere';


        $fields = array('id' => $id, 'latitude' => $lat, 'longitude' => $lon);

//http header
        $headers = array('Authorization: key=' . $apiKey,
        'Content-Type: application/json');

//curl connection
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));

        $result = curl_exec($ch);

        curl_close($ch);

        echo $result;
        }

我想到的是,当应用程序 1 客户端想要通信时,它会向您的应用程序服务器发送一条消息。然后,应用服务器向所有适当的移动设备发送 GCM 推送消息,每个设备上的应用 2 客户端接收消息,确定其当前位置,并使用上游消息将其位置发送到应用服务器。应用程序服务器确定最近的设备(可能需要等待几秒钟才能获得所有各种响应),然后将推送消息发送到最近的应用程序 2 客户端(以及可选的应用程序 1 客户端),并提供适当的信息。

编辑:包括一些上游和下游消息的示例代码。总的来说,我排除了一般消息传递的东西。您可以用自己的东西替换 "contents" 和 "username" 字段,并且需要有不同类型的上游消息

下游消息(应用服务器端 - 在 Java 中)

public void actionPerformed(ActionEvent e) {
    // who are we sending it to?
    String toAddr = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";

    // create the message
    Map<String, Object> message = new HashMap<String, Object>();
    message.put("to", toAddr);
    message.put("message_id", myNextMessageId());

    HashMap<String, String> dataPayload = new HashMap<>();
    dataPayload.put( "contents", dataInfo.getText() );

    message.put("data", dataPayload);

    // actually send the message
    try {
            Packet request = new GcmPacketExtension(JSONValue.toJSONString(message)).toPacket();
            connection.sendPacket(request);
    } catch ( NotConnectedException enc ) {
        // quietly ignore the error
    }
}

下游消息(Android 客户端)

public class MyGcmListenerService extends GcmListenerService {
    public MyGcmListenerService() { }

    public void onMessageReceived (String from, Bundle data) {
        // get info ("data" stuff)
        String contents = data.getString( "contents" );

        ... process contents
    }
}

上游消息(Android 客户端)

GoogleCloudMessaging gcm;
String SENDER_ID = "999999999999";

// send the registration to the back-end app server
private void sendUpstreamMessage( user ) {
    // use upstream message to register with the app server
    //    app server uses the 'from' field of the message
    String msg = "";
    try {
        Bundle data = new Bundle();
        String user = getGoogleAccount();

        // username is the user email
        data.putString( "username", user );
        // and note this is a registration request
        data.putString("my_action", "edu.eku.styere.gcmpushclient.REGISTER");

        String id = myNewMessageId();

        // send the registration message
        gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);
    } catch (IOException ex) {
        // for now ignore error
    }
    return;
}

上游消息(应用服务器 - 在 Java 中再次出现)

// assume we already know this is an upstream message and not an ACK or something else
protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
    // PackageName of the application that sent this message.
    String category = (String) jsonObject.get("category");
    String from = (String) jsonObject.get("from");
    @SuppressWarnings("unchecked")
    Map<String, String> payload = (Map<String, String>) jsonObject.get("data");

    // what action do they want?
    String my_action = (String) payload.get( "my_action" );
    if ( my_action.equals( "edu.eku.styere.gcmpushclient.REGISTER" ) ) {
    // registration request
    String username = (String) payload.get( "username" );

    registerUser( username, from );

    return;
    }
}