我们在亚马逊应用商店中的一款应用也遇到了同样的问题。在我们的案例中,我们意识到只有当这三个条件为真时才会出现问题:
- Kindle Fire HD
- Facebook 应用程序已安装且用户已登录
- 用户还通过设置 -> 我的帐户 -> 管理社交帐户登录了 facebook
这可以解释为什么在你的情况下它只发生在 5% 的情况下。
据我们所知,亚马逊放弃了 .apk,这打破了 Facebook Android App Key Hash 检查。
涉及的解决方案:
- 获取我们app的Amazon.apk(不是我们提交的,是亚马逊appstore分发的)
- 从 .apk 文件中提取签名证书
- Base64 对编码证书的 SHA 摘要进行编码
- 将生成的 Base64 密钥哈希添加到我们的 Facebook 应用设置
这解决了问题。
事实证明,获取 .apk 很棘手。应用程序位于设备文件系统的 /data/app 文件夹中。但是,此目录受到保护以防止将其列出,因此除非您知道要查找的文件的名称,否则您就不走运了。当然,您可以根设备。或者,您可以通过adb pull /data/app/<app-id><suffix>.apk
where suffix is a empty string 或-1
,-2
等来试试运气,直到成功。例如:
$ adb pull /data/app/com.example.game.apk
remote object '/data/app/com.example.game.apk' does not exist
$ adb pull /data/app/com.example.game-1.apk
remote object '/data/app/com.example.game-1.apk' does not exist
$ adb pull /data/app/com.example.game-2.apk
3658 KB/s (1085140 bytes in 0.289s)
如果这种方法失败,生根可能是唯一的选择。
获得 .apk 文件后,您可以使用下面的代码来获取密钥哈希。另存为Main.java
,编译javac Main.java
并运行java Main <APK>
,例如:
$ javac Main.java
$ java Main com.example.game-1.apk
com.example.game-1.apk: 478uEnKQV+fMQT8Dy4AKvHkYibo=
添加478uEnKQV+fMQT8Dy4AKvHkYibo=
到我们的 Facebook 应用程序设置的密钥散列然后解决问题。我很好奇其他人是否找到我们得到的相同哈希(这意味着所有亚马逊游戏都使用相同的密钥退出)。在我们的例子中,哈希以wwYPegrz...
.
这是代码:
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import sun.misc.BASE64Encoder;
public class Main {
public static void main(String[] args) throws Exception {
for (String jarFilename : args)
extractHash(jarFilename);
}
private static void extractHash(String jarFilename) throws Exception {
BASE64Encoder base64 = new BASE64Encoder();
MessageDigest sha1 = MessageDigest.getInstance("SHA");
Set<Certificate> certificates = new HashSet<Certificate>();
JarFile jarFile = new JarFile(jarFilename);
for (JarEntry jarEntry : Collections.list(jarFile.entries())) {
jarFile.getInputStream(jarEntry).skip(Long.MAX_VALUE);
Certificate[] certs = jarEntry.getCertificates();
if (certs == null)
continue;
certificates.addAll(Arrays.asList(certs));
}
System.out.printf("%s:", jarFilename);
for (Certificate cert : certificates) {
byte[] digest = sha1.digest(cert.getEncoded());
System.out.printf(" %s", base64.encode(digest));
}
if (certificates.isEmpty())
System.out.printf(" NOT SIGNED!");
System.out.println();
jarFile.close();
}
}