如何在android中实现C2DM?

发布于 2024-11-17 00:47:48 字数 8414 浏览 2 评论 0原文

我正在搜索如何使用 C2DM 发送通知。我发现了一些东西,并使用它可以生成注册密钥以及身份验证密钥

但之后在 ServerSimulator 类(服务器端代码)中,我收到 401 错误(401 未经授权)。现在我手动传递用户名和密码,并在 Android 设备中同步。我得到和以前一样的错误。

当我单击“发送消息”按钮时,我遇到了这个问题。

我陷入了这个查询。有人设法做到这一点吗?

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);
        }
    }
}

I am searching about how to send notification using C2DM. I found something and using that I am able to generate Registration Key as well as an Authentication Key.

But after that in ServerSimulator class (sever side code) I got 401 Error (401 Unauthorized).Now I passed Username and Password manually, which I synchronized in my Android device. I get same error as before.

I face this problem when I click on send message button..

I am stuck on this query. Has anyone managed to do this?

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);
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失退 2024-11-24 00:47:48

您目前正在以较旧的方式实施 C2DM。您所做的方式提供了很多可定制性,但没有多少人需要这种可定制性。通过新的 Google Plugin 2.4 Beta,他们实际上已经开始将所有内容集成进来,这非常好。

我强烈建议您观看 Google IO Android + AppEngine。他们展示了如何非常非常简单地将 Android、AppEngine 和 C2DM 集成在一起。您可以创建一些他们称之为“AppEngine Connected Android Project”的东西。因此,您不必制作服务器模拟器,而是实际上使用可以免费设置的真实服务器。

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

如果您愿意移动到另一台服务器,您必须重新编写服务器端代码,然后只需更改它发布到的 URL。很简单。我强烈建议您查看这个示例并使用库存代码,因为它为您提供了一些可以立即使用的东西:

仅供参考,当前代码中存在一个错误(因为它是在 beta atm 中),当它注册到真正托管的应用程序引擎服务器(本地一切正常)。它尝试发送过期的注册令牌。我一直在与谷歌开发人员联系,他们为我提供了修复程序。如果您达到了需要的程度,请告诉我。

You are currently implementing C2DM in an older way. The way you are doing offers a lot of customizability, but not many people need that kind of customizability. With the new Google Plugin 2.4 Beta they have actually started integrating it all in, and it's pretty nice.

I'd highly recommend you watch the Google IO Android + AppEngine. They show how to integrate Android, AppEngine, and C2DM together really really simply. You can create something they call an "AppEngine Connected Android Project". So instead of making a ServerSimulator, you'd be actually working with a real server that can all be setup for free.

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

If you wanted to move to another server, you'd have to re-write the server-side code, and then just change the URL that it's posting to. Pretty simple. I'd highly recommend checking out this example and working with the stock code, as it gives you something working right off the bat to play with:

FYI, there is currently a bug in the code (as it is in beta atm) when it comes to registering to a real hosted appengine server (everything works fine locally). It tries to send an expired registration token. I've been in contact with the google developers and they provided a fix for me. Let me know if you get to the point where you need it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文