草庐IT

Android c2dm自动注销

coder 2023-12-15 原文

当我向设备发送通知时,该设备收到推送消息,但它收到“com.google.android.c2dm.intent.REGISTRATION” Intent ,而不是“com.google.android.c2dm.intent” 。收到”。 如果我尝试发送第二个通知,我会收到来自 Google 的“NotRegistered”错误。

设备注册正常(我猜),因为我获得了身份验证 token “APA91...-119 个字符-”。

这是我开始注册设备的代码:

Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "EMAIL");
startService(registrationIntent);

发件人(这是在 Android 设备中完成的):

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", "SAME AS LOGIN"));
        nameValuePairs.add(new BasicNameValuePair("Passwd", "****"));
        nameValuePairs.add(new BasicNameValuePair("accountType", "HOSTED_OR_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("C2DM", line);
            if (line.startsWith("Auth=")) {
                s = line.substring(5);//LOGIN TOKEN
                Log.i("C2DM", "Token get: "+ s);
                    String auth_key = s; /* GETTING THE AUTH TOKEN FROM SERVER */
                    StringBuilder postDataBuilder = new StringBuilder();
                    postDataBuilder.append(PARAM_REGISTRATION_ID).append("=").append(auth_key);
                    postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=").append("0");
                    postDataBuilder.append("&").append("data.info").append("=").append(URLEncoder.encode("Invitar", UTF8));
            URLEncoder.encode(telephonyManager.getDeviceId(), UTF8));

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

            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("C2DM", String.valueOf(responseCode));
            // Validate the response code

            if (responseCode == 401 || responseCode == 403) {
                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();

            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("C2DM", "Successfully sent data message to device: "+ responseLine);
                retval = 1;
            }

            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);
            }
                return sendMessage();
            }

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

我的收件人:

public void onReceive(Context context, Intent intent) {
    Log.d("C2DM", "Intent recieved: "+intent.getAction());
    if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
        handleRegistration(context, intent);
    } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
        handleMessage(context, intent);
    }
 }

private void handleRegistration(Context context, Intent intent) {
    String registration = intent.getStringExtra("registration_id");
    if (intent.getStringExtra("error") != null) {
        // Registration failed, should try again later.
        Log.d("C2DM", "registration failed");
        String error = intent.getStringExtra("error");
        if(error == "SERVICE_NOT_AVAILABLE"){
            Log.d("c2dm", "SERVICE_NOT_AVAILABLE");
        }else if(error == "ACCOUNT_MISSING"){
            Log.d("c2dm", "ACCOUNT_MISSING");
        }else if(error == "AUTHENTICATION_FAILED"){
            Log.d("c2dm", "AUTHENTICATION_FAILED");
        }else if(error == "TOO_MANY_REGISTRATIONS"){
            Log.d("c2dm", "TOO_MANY_REGISTRATIONS");
        }else if(error == "INVALID_SENDER"){
            Log.d("c2dm", "INVALID_SENDER");
        }else if(error == "PHONE_REGISTRATION_ERROR"){
            Log.d("c2dm", "PHONE_REGISTRATION_ERROR");
        }
    } else if (intent.getStringExtra("unregistered") != null) {
        //HERE IS WHERE ARRIVES THE SEND NOTIFICATION (NOT THE UNREGISTER NOTIFICATION)
        Log.d("C2DM", "unregistered: "+intent.getStringExtra("unregistered"));

    } else if (registration != null) {
        Log.d("C2DM", registration);
        /* SENDING THE AUTH TOKET TO SERVER */
    }
}

我在设备上推送通知,因为如果我在服务器端推送通知,我总是会收到“InvalidRegistration”错误。

奇怪的是,我好像注册了,但是当我发送一条推送消息时,就像谷歌取消注册设备一样。

有什么想法/建议吗?

最佳答案

我遇到了同样的问题并解决了它。

这是错误的代码

<receiver android:name=".MyC2DMReceiver"
            android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
          <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
          <category android:name="com.package.myapp" />
      </intent-filter>
      <intent-filter>
          <action android:name="com.google.android.c2dm.permission.RECEIVE" />
          <category android:name="com.package.myapp" />
      </intent-filter>
  </receiver>

我有写 Intent 而不是许可

com.google.android.c2dm.permission.RECEIVE => com.google.android.c2dm.intent.RECEIVE

然后它就正常工作了 所以RECEIVE的包名是错误的

正确的代码

<receiver android:name=".MyC2DMReceiver"
            android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
          <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
          <category android:name="com.package.myapp" />
      </intent-filter>
      <intent-filter>
          <action android:name="com.google.android.c2dm.intent.RECEIVE" />
          <category android:name="com.package.myapp" />
      </intent-filter>
  </receiver>

关于Android c2dm自动注销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6097980/

有关Android c2dm自动注销的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  4. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  5. ruby - 在 ruby​​ 中使用自动创建插入数组 - 2

    我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?

  6. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  7. ruby-on-rails - Devise 在更改密码后注销用户 - 2

    我正在使用devise,当用户更改密码时,网站会将他们注销。我在网上读到,添加sign_in可以解决问题但不起作用,并且当密码更改时用户会注销。这是我的代码if@user.errors[:base].empty?and@user.update_attributes(params[:user])sign_in(current_user,:bypass=>true)flash[:success]="Useraccounthasbeensuccessfullyupdated"redirect_toedit_user_path(params[:site_id],@user)elserender

  8. 【自动驾驶环境感知项目】——基于Paddle3D的点云障碍物检测 - 2

    文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3

  9. ruby-on-rails - 自动完成搜索的 Rails 实现 - 2

    我不确定如何为我的搜索功能添加自动完成表单。"get"do%>nil%>我有一个具有自定义操作的Controllerdefquery@users=Search.user(params[:query])@article=Search.article(params[:query])end模型如下:defself.user(search)ifsearchUser.find(:all,:conditions=>['first_nameLIKE?',"%#{search}%"])elseUser.find(:all)endenddefself.article(search)ifsearchArt

  10. ruby - 如何设置自动测试以仅重新运行失败的 rspec 示例 - 2

    我对自动测试的工作方式的印象(基于cucumbergithubwiki和其他在线内容)是它应该重新运行红色示例,直到它们通过。我的问题是它会重新运行规范文件中找到失败示例的所有示例,包括通过的示例。我不想浪费时间在修复失败示例的同时重新运行通过的示例。是否可以配置自动测试以便仅运行失败的示例? 最佳答案 您需要rspec-retrygem。以下是文档中有关如何实现它的一些示例:将它应用到覆盖整个测试套件的configureblock中...RSpec.configuredo|config|config.verbose_retry=t

随机推荐