从Google Play下载时,Android应用程序崩溃,但在本地开发人员中运行良好-为什么?

我不确定是否有人可以提供帮助,但这确实很奇怪。我构建了一个android应用程序,并在本地对其进行了测试,一切正常。然后,我将其发布到应用程序商店,并且一直崩溃。

谷歌播放的堆栈跟踪显示:

java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:300)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
    at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
    at libcore.net.UriCodec.encode(UriCodec.java:132)
    at java.net.URLEncoder.encode(URLEncoder.java:57)
    at com.xxxx.yyyy.bbbb.SignedRequestsHelper.percentEncodeRfc3986(SignedRequestsHelper.java:120)
    at com.xxxx.yyyy.bbbb.SignedRequestsHelper.sign(SignedRequestsHelper.java:63)
    at com.xxxx.yyyy.SearchFragment$SearchAsyncTask.doInBackground(SearchFragment.java:385)
    at com.xxxx.yyyy.SearchFragment$SearchAsyncTask.doInBackground(SearchFragment.java:338)
    at android.os.AsyncTask$2.call(AsyncTask.java:288)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    ... 4 more

因此,看来我的SignedRequestsHelper.percentEncodeRfc3986()方法正在执行某些操作字符串是null但是请注意,在开发应用程序并在不同设备上进行测试时,不会发生此错误。只有在将其上传到Google Play并从那里下载后,此错误才会出现。

所以我看了看我的SignedRequestHelper类,当时的样子是这样的:

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class SignedRequestsHelper {
    private static final String UTF8_CHARSET = "UTF-8";
    private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
    private static final String REQUEST_URI = "/onca/xml";
    private static final String REQUEST_METHOD = "GET";

    // use xml-uk.amznxslt.com for xslt requests, or ecs.amazonaws.co.uk for others
    private String endpoint = "webservices.amazon.com"; // must be lowercase

    // change this so reads from properties file
    private String awsAccessKeyId = "xxxx";
    private String awsSecretKey = "xxx";

    private SecretKeySpec secretKeySpec = null;
    private Mac mac = null;

    public SignedRequestsHelper() throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
        byte[] secretyKeyBytes = awsSecretKey.getBytes(UTF8_CHARSET);
        secretKeySpec =
                new SecretKeySpec(secretyKeyBytes, HMAC_SHA256_ALGORITHM);
        mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
        mac.init(secretKeySpec);
    }

    public String sign(Map<String, String> params) {
        params.put("AWSAccessKeyId", awsAccessKeyId);
        params.put("Timestamp", timestamp());

        SortedMap<String, String> sortedParamMap =
                new TreeMap<String, String>(params);
        String canonicalQS = canonicalize(sortedParamMap);
        String toSign =
                REQUEST_METHOD + "\n"
                        + endpoint + "\n"
                        + REQUEST_URI + "\n"
                        + canonicalQS;

        String hmac = hmac(toSign);
        String sig = percentEncodeRfc3986(hmac);
        String url = "http://" + endpoint + REQUEST_URI + "?" +
                canonicalQS + "&Signature=" + sig;

        return url;
    }

    private String hmac(String stringToSign) {
        String signature = null;
        byte[] data;
        byte[] rawHmac;
        try {
            data = stringToSign.getBytes(UTF8_CHARSET);
            rawHmac = mac.doFinal(data);
            Base64 encoder = new Base64();
            signature = new String(encoder.encode(rawHmac));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(UTF8_CHARSET + " is unsupported!", e);
        }
        return signature;
    }

    private String timestamp() {
        String timestamp = null;
        Calendar cal = Calendar.getInstance();
        DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        dfm.setTimeZone(TimeZone.getTimeZone("GMT"));
        timestamp = dfm.format(cal.getTime());
        return timestamp;
    }

    private String canonicalize(SortedMap<String, String> sortedParamMap)
    {
        if (sortedParamMap.isEmpty()) {
            return "";
        }

        StringBuffer buffer = new StringBuffer();
        Iterator<Map.Entry<String, String>> iter =
                sortedParamMap.entrySet().iterator();

        while (iter.hasNext()) {
            Map.Entry<String, String> kvpair = iter.next();
            buffer.append(percentEncodeRfc3986(kvpair.getKey()));
            buffer.append("=");
            buffer.append(percentEncodeRfc3986(kvpair.getValue()));
            if (iter.hasNext()) {
                buffer.append("&");
            }
        }
        String cannoical = buffer.toString();
        return cannoical;
    }

    private String percentEncodeRfc3986(String s) {
        String out;
        try {
            out = URLEncoder.encode(s, UTF8_CHARSET)
                    .replace("+", "%20")
                    .replace("*", "%2A")
                    .replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            out = s;
        }
        return out;
    }
}

然后我将percentEncodeRfc3986()方法更改为如下所示。只需删除最后两个替换标签:

private String percentEncodeRfc3986(String s) {
        String out;
        try {
            out = URLEncoder.encode(s, UTF8_CHARSET)
                    .replace("+", "%20");
        } catch (UnsupportedEncodingException e) {
            out = s;
        }
        return out;
    }

然后在本地对其进行测试:它可以工作。然后将其发布到Google Play并下载:它有效。

因此,一切都很好,但是我留在这里想知道为什么现在这确实起作用了

这也让我感到紧张,因为当应用程序上传到Google Play时,突然之间在我的模拟器和测试设备上完美运行的代码无法正常工作。这似乎是一件微不足道的事情...一些额外的替换导致此错误。

有人可以帮我了解这里发生了什么吗?或者至少至少为什么有时发布在Google Play上的应用程序上的代码可能无法像在本地dev中那样完全无法工作或执行?

编辑:我的build.gradle文件:

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.xxx.yyy"
        minSdkVersion 10
        targetSdkVersion 22
        versionCode 8
        versionName "1.2"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

经过一些测试后,我确定出现此错误的原因是因为我最初发布App时没有更新SDK和Android Studio中的其他更新。因为在更新后,我将代码恢复为崩溃时的样子,并且一切正常-这是有道理的,因为我真的没有理由不认为我的代码无法正常工作。

因此,在这里的课程是,在签署应用的发布版本之前,请确保所有SDK工具和Android Studio都是最新的!

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何为Google开发人员下载示例应用程序?

来自分类Dev

为什么我开发的Android应用程序无法通过Google Play自动更新?

来自分类Dev

Android)的微信开发人员的应用程序签名。我要输入什么值?

来自分类Dev

为什么我的应用程序在首次打开时会在Google Play上崩溃?

来自分类Dev

有没有办法从Google Play上的开发人员那里获取所有应用程序

来自分类Dev

Google Chrome开发人员工具中的“用户样式表”是什么?

来自分类Dev

Google Chrome开发人员工具中的“用户样式表”是什么?

来自分类Dev

为什么游戏开发人员避免在应用程序级别使用TCP并使UDP可靠?

来自分类Dev

Android开发人员未在Textview中使用线程:为什么这会崩溃?

来自分类Dev

Google App开发人员:更改应用程序的默认语言

来自分类Dev

为什么当我将Fragment for Google Maps放到我的应用程序中时

来自分类Dev

UI5开发人员指南中的应用程序库是什么?

来自分类Dev

为什么Google会在某些应用程序中隐藏android.permission.VIBRATE?

来自分类Dev

为什么在Android开发人员中找不到“ ACTION_REQUEST_SHUTDOWN”?

来自分类Dev

为什么我的应用程序(使用Google Maps API 2)每次都会崩溃?

来自分类Dev

Android开发-为什么该应用程序崩溃?

来自分类Dev

在设备上没有相机的Android用户无法从Google Play下载我的应用-为什么?

来自分类Dev

为什么Google Play商店未显示应用程序设备不可用的原因?

来自分类Dev

为什么我无法在Google Play商店中找到官方的Github移动应用程序?

来自分类Dev

为什么要为每个Chrome应用程序窗口打开一个新的“开发人员工具”窗口?

来自分类Dev

在将React应用程序部署到Heroku后,为什么Chrome React开发人员工具仍然显示红色

来自分类Dev

为什么在我的本地存储库中我会看到其他开发人员的提交?

来自分类Dev

什么是Youtube开发人员密钥?我可以在Google Developer Console中找到它吗?

来自分类Dev

为什么google_play_service_lib在Eclipse中损坏?

来自分类Dev

为什么Google Developers Console中缺少GAE应用程序?

来自分类Dev

使用两个不同的开发人员姓名进行Google Play应用发布

来自分类Dev

Android上的Google Chrome扩展程序开发的开发人员指南

来自分类Dev

MS Access 2010子报表运行良好,但主报表冻结,仅对用户有效,对开发人员无效。为什么以及如何解决?

来自分类Dev

无法运行Google Glass开发人员示例

Related 相关文章

  1. 1

    如何为Google开发人员下载示例应用程序?

  2. 2

    为什么我开发的Android应用程序无法通过Google Play自动更新?

  3. 3

    Android)的微信开发人员的应用程序签名。我要输入什么值?

  4. 4

    为什么我的应用程序在首次打开时会在Google Play上崩溃?

  5. 5

    有没有办法从Google Play上的开发人员那里获取所有应用程序

  6. 6

    Google Chrome开发人员工具中的“用户样式表”是什么?

  7. 7

    Google Chrome开发人员工具中的“用户样式表”是什么?

  8. 8

    为什么游戏开发人员避免在应用程序级别使用TCP并使UDP可靠?

  9. 9

    Android开发人员未在Textview中使用线程:为什么这会崩溃?

  10. 10

    Google App开发人员:更改应用程序的默认语言

  11. 11

    为什么当我将Fragment for Google Maps放到我的应用程序中时

  12. 12

    UI5开发人员指南中的应用程序库是什么?

  13. 13

    为什么Google会在某些应用程序中隐藏android.permission.VIBRATE?

  14. 14

    为什么在Android开发人员中找不到“ ACTION_REQUEST_SHUTDOWN”?

  15. 15

    为什么我的应用程序(使用Google Maps API 2)每次都会崩溃?

  16. 16

    Android开发-为什么该应用程序崩溃?

  17. 17

    在设备上没有相机的Android用户无法从Google Play下载我的应用-为什么?

  18. 18

    为什么Google Play商店未显示应用程序设备不可用的原因?

  19. 19

    为什么我无法在Google Play商店中找到官方的Github移动应用程序?

  20. 20

    为什么要为每个Chrome应用程序窗口打开一个新的“开发人员工具”窗口?

  21. 21

    在将React应用程序部署到Heroku后,为什么Chrome React开发人员工具仍然显示红色

  22. 22

    为什么在我的本地存储库中我会看到其他开发人员的提交?

  23. 23

    什么是Youtube开发人员密钥?我可以在Google Developer Console中找到它吗?

  24. 24

    为什么google_play_service_lib在Eclipse中损坏?

  25. 25

    为什么Google Developers Console中缺少GAE应用程序?

  26. 26

    使用两个不同的开发人员姓名进行Google Play应用发布

  27. 27

    Android上的Google Chrome扩展程序开发的开发人员指南

  28. 28

    MS Access 2010子报表运行良好,但主报表冻结,仅对用户有效,对开发人员无效。为什么以及如何解决?

  29. 29

    无法运行Google Glass开发人员示例

热门标签

归档