在我的小应用程序中,我从系统(不受我控制)收到一系列排队的onEventXXX().
那些onEventXXX()的时间不保证.唯一保证的是它们按照它们被放入队列的顺序被接收.
在onEventXXX()中,我必须触发一个操作(O),当另一个进程(P)进行时,该操作无法启动.
但我不能放弃这个"开火行动(O)".我必须等到那个过程(P)完成,然后解雇它.
IOW,我必须排队或至少推迟"触发操作"直到该过程(P)完成.
我实现这一点的直接想法是,不是解雇操作(O),而是:
但是,知道Android的丰富性,我怀疑有一种更好的方法,已经内置到系统/ API中.
如果有更好的方法来实现上述目标,它会是什么?
为了测试我不想释放功能的缘故还向广大市民,我想实现一个"秘密"菜单或菜单项.
通过"秘密"我的意思不是真正的秘密,但更多的是隐藏的或不可见的菜单,访问开发者(我)只能通过输入代码或其他机制.
如果最终用户发现它并尝试使用它这不是世界末日("他们做这白痴证明,但我找到了一个解决办法.").我只是不想通过提供尚未完全测试的功能而让毫无防备的无辜的最终用户失败.
关于如何解决这个问题的任何建议?(仅限Android 2.2及以上版本)
使用PURCHASE_STATE_CHANGED意图返回的JSON字段包含非常有用的信息,但我没有列出我感兴趣的一件:客户的电子邮件地址.
有没有办法使用In-App Billing API检索它?
如果没有,有没有办法为客户检索一些其他唯一标识符,以便交易可以与客户而不是设备相关联?
为了能够测试Android Market许可的任何实施(例如LVL,应用程序内结算),Google建议创建一个Google Checkout 测试帐户,因为开发人员无法使用自己的Google Checkout帐户自行购买.
听起来不错,除了测试帐户必须使用真实的信用卡.
这引出了一个问题:这与普通账户有什么不同?普通帐户的测试帐户有什么优势?
应用内结算概述中的安全控制部分指示在远程服务器而不是应用程序(在Android设备上本地运行)执行"签名验证":
通过执行签名验证,您可以帮助检测已被篡改或已被欺骗的响应.您可以在应用程序中执行此签名验证步骤; 但是,如果您的应用程序连接到安全的远程服务器,那么我们建议您在该服务器上执行签名验证.
但是,如果我在远程服务器上执行签名验证,只期望一个yes/no或true/false答案,这实际上是不是更容易被攻击者拦截和修改?
如果来自远程服务器的答案是另一个签名,那么如何在设备上本地验证第二个签名比第一个(市场)签名更安全?
我错过了什么?
更新: @alf正确地指出,如果服务器还负责提供购买的内容并且在服务器上执行签名验证,那么即使攻击者破坏了应用程序,服务器也不会提供通过应用程序内计费购买的内容.这是微不足道的,也是很好理解的.
我最初没有提到的是,我实际上指的是服务器不提供任何内容而只是验证签名的场景,以便应用程序可以决定是否解锁某些功能.在这种情况下,远程服务器签名验证优于应用程序内的优势是什么?
我只添加了一个现有的完全工作项目,该文件 com/android/vending/billing/IMarketBillingService.aidl
(我没有添加任何其他内容(来自market_billing样本),因为我甚至没有尝试使用该服务)
它编译和构建完美,但当我尝试运行它时,我在控制台中收到以下内容:
java.lang.IllegalArgumentException: already added: Lcom/android/vending/billing/IMarketBillingService$Stub$Proxy;
Dx at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
Dx at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
Dx at com.android.dx.command.dexer.Main.processClass(Main.java:486)
Dx at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
Dx at com.android.dx.command.dexer.Main.access$400(Main.java:67)
Dx at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
Dx at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
Dx at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
Dx at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
Dx at com.android.dx.command.dexer.Main.processOne(Main.java:418)
Dx at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
Dx at com.android.dx.command.dexer.Main.run(Main.java:206)
Dx at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Dx at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
Dx at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Dx at java.lang.reflect.Method.invoke(Unknown Source)
Dx at com.android.ide.eclipse.adt.internal.build.DexWrapper.run(DexWrapper.java:179)
Dx at com.android.ide.eclipse.adt.internal.build.BuildHelper.executeDx(BuildHelper.java:745)
Dx at com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.build(PostCompilerBuilder.java:634)
Dx at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:629)
Dx at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
Dx at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:172)
Dx at …Run Code Online (Sandbox Code Playgroud) 给定一个理论系统,如果在本地系统中找不到文件,则从 Web 下载文件并假设:
我编写了一个方法,使用 getFileFromLocalFS() 和 getFileFromWeb() 来实现简化的缓存逻辑:
public InputStream getFile(String url) { // #1
InputStream retStream = getFileFromLocalFS(url);
if (retStream != null) {
return retStream;
}
else {
retStream = getFileFromLocalFS(url);
if (retStream == null) {
return getFileFromWeb(url);
}
}
return retStream;
}
Run Code Online (Sandbox Code Playgroud)
然后需要改进这个示意性解决方案,以适应从同一 URL 下载的并发请求...并将实际的“从 Web”限制为单个下载(即所有其他请求将从本地文件系统获取它)。所以,我同步了整个方法:
public synchronized InputStream getFile(String url) { // #2
InputStream retStream = getFileFromLocalFS(url);
if (retStream != null) {
return retStream;
}
else {
retStream = getFileFromLocalFS(url); …Run Code Online (Sandbox Code Playgroud) 我希望能够在应用程序启动时将运行版本与当前在 Google Play 上的相同应用程序版本进行比较。
我找到了一个很好的方法,在这里描述:
public String getLatestVersionNumber() {
String versionNumber = "0.0.0";
try {
Document doc = Jsoup.connect("http://www.appbrain.com/app/wallpaper-switch/com.mlevit.wallpaperswitch").get();
Elements changeLog = doc.select("div.clDesc");
for (Element div : changeLog) {
String divText = div.text();
if (divText.contains("Version")) {
return divText.split(" ")[1];
}
}
}
catch (IOException e) {
e.printStackTrace();
}
return versionNumber;
}
Run Code Online (Sandbox Code Playgroud)
但是它太慢了,并且严重妨碍了应用程序启动时的用户体验。
是否有更快的方法在 Google Play 上查询应用程序的当前版本?
也许是一些隐藏的 LVL 或应用内计费 API?
android ×6
android-lvl ×2
google-play ×2
java ×2
aidl ×1
android-menu ×1
concurrency ×1
dalvik ×1
decompiling ×1
encryption ×1
synchronized ×1