4 Stimmen

Wie implementiert man C2DM in Android?

Ich bin auf der Suche, wie ich mit C2DM eine Benachrichtigung senden kann. Ich habe etwas gefunden, mit dem ich Folgendes generieren kann Registration Key sowie eine Authentication Key .

Aber danach in ServerSimulator Klasse (sever side code) bekam ich 401 Fehler (401 Unauthorized). jetzt habe ich Benutzername und Passwort manuell übergeben, die ich in meinem Android-Gerät synchronisiert. Ich erhalte denselben Fehler wie zuvor.

Ich habe dieses Problem, wenn ich auf die Schaltfläche "Nachricht senden" klicke.

Ich komme bei dieser Frage nicht weiter. Hat es jemand geschafft, dies zu tun?

public class ServerSimulator extends Activity 
{
    private SharedPreferences prefManager;
    private final static String AUTH = "authentication";

    private static final String UPDATE_CLIENT_AUTH = "Update-Client-Auth";

    public static final String PARAM_REGISTRATION_ID = "registration_id";

    public static final String PARAM_DELAY_WHILE_IDLE = "delay_while_idle";

    public static final String PARAM_COLLAPSE_KEY = "collapse_key";

    private static final String UTF8 = "UTF-8";

    // Registration is currently hardcoded
    private final static String YOUR_REGISTRATION_STRING = "APA91bFkxmtIj5XiBU-Cze64s0gXNb7OmiWWZg-qLKibpLsVXaWq1X7hoRV9Ld9COYXirZAgkYegZBdBfUGt3lgtuhNJopvHB0KJ5ZyJ6Kt_HYRrZhgdJ1Y";

    private SharedPreferences prefs;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        prefManager = PreferenceManager.getDefaultSharedPreferences(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.mymenu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menuitem_user:
            Intent intent = new Intent(this, UserPreferences.class);
            startActivity(intent);
            break;
        default:
            break;
        }
        return false;
    }

    public void getAuthentification(View view) {
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(
                "https://www.google.com/accounts/ClientLogin");

        try {

            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
            nameValuePairs.add(new BasicNameValuePair("Email","myEmail id")));
            nameValuePairs.add(new BasicNameValuePair("Passwd","my password")));
            nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
            nameValuePairs.add(new BasicNameValuePair("source","Google-cURL-Example"));
            nameValuePairs.add(new BasicNameValuePair("service", "ac2dm"));

            post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = client.execute(post);
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent()));

            String line = "";
            while ((line = rd.readLine()) != null) {
                Log.e("HttpResponse", line);
                if (line.startsWith("Auth=")) {
                    Editor edit = prefManager.edit();
                    edit.putString(AUTH, line.substring(5));
                    edit.commit();
                    String s = prefManager.getString(AUTH, "n/a");
                    Toast.makeText(this, s, Toast.LENGTH_LONG).show();
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void showAuthentification(View view) {
        String s = prefManager.getString(AUTH, "n/a");
        Toast.makeText(this, s, Toast.LENGTH_LONG).show();
    }

    public void sendMessage(View view) {
        try {
            Log.e("Tag", "Started");
            String auth_key = prefManager.getString(AUTH, "n/a");
            // Send a sync message to this Android device.
            StringBuilder postDataBuilder = new StringBuilder();
            postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
                    .append(YOUR_REGISTRATION_STRING);

            // if (delayWhileIdle) {
            // postDataBuilder.append("&").append(PARAM_DELAY_WHILE_IDLE)
            // .append("=1");
            // }
            postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
                    .append("0");

            postDataBuilder.append("&").append("data.payload").append("=")
                    .append(URLEncoder.encode("Lars war hier", UTF8));

            byte[] postData = postDataBuilder.toString().getBytes(UTF8);

            // Hit the dm URL.

            URL url = new URL("https://android.clients.google.com/c2dm/send");

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded;charset=UTF-8");
            conn.setRequestProperty("Content-Length",
                    Integer.toString(postData.length));
            conn.setRequestProperty("Authorization", "GoogleLogin auth="
                    + auth_key);

            OutputStream out = conn.getOutputStream();
            out.write(postData);
            out.close();

            int responseCode = conn.getResponseCode();

            Log.e("Tag", String.valueOf(responseCode));
            // Validate the response code

            if (responseCode == 401 || responseCode == 403) {
                // The token is too old - return false to retry later, will
                // fetch the token
                // from DB. This happens if the password is changed or token
                // expires. Either admin
                // is updating the token, or Update-Client-Auth was received by
                // another server,
                // and next retry will get the good one from database.
                Log.e("C2DM", "Unauthorized - need token");
            }

            // Check for updated token header
            String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
            if (updatedAuthToken != null && !auth_key.equals(updatedAuthToken)) {
                Log.i("C2DM",
                        "Got updated auth token from datamessaging servers: "
                                + updatedAuthToken);
                Editor edit = prefManager.edit();
                edit.putString(AUTH, updatedAuthToken);
            }

            String responseLine = new BufferedReader(new InputStreamReader(
                    conn.getInputStream())).readLine();

            // NOTE: You *MUST* use exponential backoff if you receive a 503
            // response code.
            // Since App Engine's task queue mechanism automatically does this
            // for tasks that
            // return non-success error codes, this is not explicitly
            // implemented here.
            // If we weren't using App Engine, we'd need to manually implement
            // this.
            if (responseLine == null || responseLine.equals("")) {
                Log.i("C2DM", "Got " + responseCode
                        + " response from Google AC2DM endpoint.");
                throw new IOException(
                        "Got empty response from Google AC2DM endpoint.");
            }

            String[] responseParts = responseLine.split("=", 2);
            if (responseParts.length != 2) {
                Log.e("C2DM", "Invalid message from google: " + responseCode
                        + " " + responseLine);
                throw new IOException("Invalid response from Google "
                        + responseCode + " " + responseLine);
            }

            if (responseParts[0].equals("id")) {
                Log.i("Tag", "Successfully sent data message to device: "
                        + responseLine);
            }

            if (responseParts[0].equals("Error")) {
                String err = responseParts[1];
                Log.w("C2DM",
                        "Got error response from Google datamessaging endpoint: "
                                + err);
                // No retry.
                throw new IOException(err);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

0voto

spierce7 Punkte 13472

Sie implementieren C2DM derzeit auf eine ältere Art und Weise. Die Art und Weise, wie Sie es tun, bietet eine Menge Anpassungsmöglichkeiten, aber nicht viele Leute brauchen diese Art von Anpassungsmöglichkeiten. Mit dem neuen Google Plugin 2.4 Beta haben sie tatsächlich begonnen, alles zu integrieren, und es ist ziemlich nett.

Ich empfehle Ihnen dringend, sich die Google IO Android + AppEngine anzusehen. Dort wird gezeigt, wie man Android, AppEngine und C2DM ganz einfach miteinander integrieren kann. Sie können etwas erstellen, das sie ein "AppEngine Connected Android Project" nennen. Anstatt also einen ServerSimulator zu erstellen, arbeiten Sie tatsächlich mit einem echten Server, der kostenlos eingerichtet werden kann.

http://www.youtube.com/watch?v=M7SxNNC429U

Wenn Sie auf einen anderen Server umziehen möchten, müssen Sie den serverseitigen Code neu schreiben und dann nur die URL ändern, an die er gesendet wird. Ziemlich einfach. Ich empfehle Ihnen, sich dieses Beispiel anzuschauen und mit dem Standardcode zu arbeiten, da Sie damit sofort etwas Funktionierendes zum Spielen haben:

FYI, gibt es derzeit einen Fehler im Code (wie es in Beta atm), wenn es um die Registrierung zu einem echten gehosteten appengine Server kommt (alles funktioniert gut lokal). Es versucht, eine abgelaufene Registrierung Token zu senden. Ich habe mich mit den Google-Entwicklern in Verbindung gesetzt und sie haben mir einen Fix zur Verfügung gestellt. Lassen Sie mich wissen, wenn Sie an den Punkt kommen, wo Sie es brauchen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X