小编Ton*_*oni的帖子

Android应用程序结算:订单取消后,购买状态保持"已购买"状态

我目前正在测试我的InApp计费机制(使用InApp Billing版本3 API,因此将TrivialDrive示例作为参考).

我有一个托管项目,即升级到高级版本.

现在,使用我的测试帐户购买该项目是有效的,但是当我之后在Google结帐中取消整个订单时,我的代码仍然告诉我该项目已购买,因此授予高级功能.

以下是我在MainActivity中检查购买的方法.我不会在某处本地保存购买状态,因为据我所知,使用billing API v3,您可以根据需要查询特定购买.

@Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();

        iabHelper = new IabHelper(this, Helper.getPKey());
        iabHelper.enableDebugLogging(true);

        iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {

            @Override
            public void onIabSetupFinished(IabResult result) {
                Log.d("IAB", "SETUP FINISHED");

                if(!result.isSuccess())
                {
                    Log.d("IAB", "SETUP NOT OK");
                    return;
                }
                else
                    Log.d("IAB", "SETUP OK");

                iabHelper.queryInventoryAsync(
                    new QueryInventoryFinishedListener() {

                        @Override
                        public void onQueryInventoryFinished(IabResult result, Inventory inv) {
                            Log.d("IAB", "Query inventory finished.");
                            if (result.isFailure()) {
                                Log.d("IAB","Failed to query inventory: " + result);
                                return;
                            }

                            Log.d("IAB", "Query inventory …
Run Code Online (Sandbox Code Playgroud)

android in-app-purchase in-app-billing

46
推荐指数
6
解决办法
3万
查看次数

如何在本地最好地保存InApp购买状态?

我正处于完成我的第一个应用程序的边缘,剩下的最后一件事就是实现IAP计费,这就是为什么我目前正在阅读相关主题(包括加密,混淆和东西等安全问题).

我的应用程序是免费版本,能够通过IAP升级到完整版本,因此只有一个托管购买项目"溢价".我有几个问题:

在Google IAP API示例(trivialdrivesample)中,总是在MainActivity中检查IAP以查看用户是否购买了高级版本,通过

mHelper.queryInventoryAsync(mGotInventoryListener);

我的第一个问题:这是否意味着用户始终需要在应用启动时拥有互联网/数据连接,才能切换到高级版本?如果用户没有互联网连接怎么办?他会选择我猜的精简版,我觉得这很烦人.

所以我想到了如何在SharedPrefs或app数据库中本地保存isPremium状态.现在,我知道你无法阻止黑客对应用程序进行逆向工程,无论如何,即便如此,因为我没有服务器来进行服务器端验证.

然而,一个人根本无法在某处保存"isPremium"标志,因为这太容易被发现.

所以我在考虑这样的事情:

  • 用户购买Premium
  • 应用程序获取IMEI/Device-ID,XOR使用硬编码的String键对其进行编码,并将其保存在应用程序数据库中.

现在,当用户再次启动应用程序时:

  • App从数据库中获取编码的String,对其进行解码并检查decodeString == IMEI.如果是 - >溢价
  • 如果不是,则将调用正常的queryInventoryAsync以查看用户是否购买了premium.

您如何看待这种方法?我知道这不是超级固定,但对我而言,更重要的是用户不会烦恼(比如强制性的互联网连接),而不是应用程序将无法解决(无论如何这是不可能的).你有其他一些提示吗?

另一件事,我目前还不知道,是当用户卸载/重新安装应用程序时如何恢复事务状态.我知道API有一些机制,并且我的数据库可以通过应用程序导出和导入(因此编码的isPremium标志也可以导出/导入).好吧,我猜这将是另一个问题,当时机成熟时;-)

对这种方法的任何想法和评论都是受欢迎的,您认为这是一个很好的解决方案吗?或者我错过了什么/朝着错误的方向前进?

security android in-app-purchase

34
推荐指数
3
解决办法
6392
查看次数

困惑:SQLiteOpenHelper onUpgrade()如何表现?和导入旧的数据库备份一起?

假设我在SQLiteOpenHelper中有一个包含2列的数据库表test_table和相应的创建脚本:

DB_VERSION = 1:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B);
}
Run Code Online (Sandbox Code Playgroud)

这是最初的应用版本1,发布在Play商店中.

过了一会儿,应用程序和使用的数据库都有更新.我想SQLiteOpenHelper类必须像这样调整:

DB_VERSION = 2:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B, COL_C)");
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSql("ALTER TABLE test_table ADD Column COL_C");
}
Run Code Online (Sandbox Code Playgroud)

一段时间后,另一个应用更新:

DB_VERSION = 3:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B, COL_C, COL_D)");
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSql("ALTER TABLE test_table ADD Column COL_D"); …
Run Code Online (Sandbox Code Playgroud)

import android export sqliteopenhelper

27
推荐指数
2
解决办法
1万
查看次数

如何在通知按钮单击后关闭状态栏/通知面板

我浏览过Stackoverflow并且已经看到这个问题已被提出,但我没有找到任何解决方案.

我有一个带2个按钮的自定义通知.我希望状态栏面板在我按下该通知上的按钮后关闭,但不知道如何.如果我按下通知本身(所以contentIntent),然后面板关闭,这也是我想要的按钮.

这是我的通知代码:

Notification notification = new Notification(R.drawable.icon, "Service running", System.currentTimeMillis());
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.contentIntent = openIntent;
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notification_layout);


contentView.setOnClickPendingIntent(R.id.button1, stopIntent);
contentView.setOnClickPendingIntent(R.id.button2, addIntent);

notification.contentView = contentView;

notificationManager.notify(NOTIFICATION_ID, notification);
Run Code Online (Sandbox Code Playgroud)

notifications android statusbar

25
推荐指数
2
解决办法
1万
查看次数

为什么我的系统覆盖所有触摸(不能与底层视图交互)

我有一个启动系统覆盖的服务.当叠加层可见时,我希望它是可触摸/检测触摸,但我想保持与它后面的屏幕的交互(后面我的意思是底层活动,例如叠加层旁边).

我的叠加层是128x128px的位图/ PNG.它被绘制,当我点击它时,我收到了触摸!记录,这很好.但是当我点击屏幕的任何其他部分时(除了叠加层)我也会接触到!记录并且没有与它下面的屏幕的交互是可能的.

以下是我的代码部分:

主要活动启动服务

buttonStart.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // start Service and return to Homescreen
                Intent i = new Intent(MainActivity.this, MyService.class);
                startService(i);                

                Intent newActivity = new Intent(Intent.ACTION_MAIN); 
                newActivity.addCategory(Intent.CATEGORY_HOME);
                newActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(newActivity);
            }
        });
Run Code Online (Sandbox Code Playgroud)

服务/显示覆盖

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        myOverlay = new Overlay(MyService.this);

        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.LEFT | Gravity.TOP;

        wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(myOverlay, params);

        myOverlay.setAnimation(new Waiting(MyService.this, 0, 0)); …
Run Code Online (Sandbox Code Playgroud)

android overlay touch-event

12
推荐指数
2
解决办法
1万
查看次数

从长远来看,Java随机总是呈现负面趋势?

我正在构建一个应用程序,为此我有一个函数来填充测试数据.简短说明:

        HashMap<String, Long> iIDs = new HashMap<String, Long>();
        HashMap<String, Integer> vals = new HashMap<String, Integer>();

        long iID1 = addIndicator("I1", "i1", Color.RED);
        long iID2 = addIndicator("I2", "i2", Color.BLUE);
        long iID3 = addIndicator("I3", "i3", Color.GREEN);
        long iID4 = addIndicator("I4", "i4", Color.MAGENTA);

        iIDs.put("iID1", iID1);
        iIDs.put("iID2", iID2);
        iIDs.put("iID3", iID3);
        iIDs.put("iID4", iID4);

        int v1 = 80;
        int v2 = 30;
        int v3 = 25;
        int v4 = 40;

        vals.put("v1", v1);
        vals.put("v2", v2);
        vals.put("v3", v3);
        vals.put("v4", v4);

        int numDays = 500;
        int dateDistance = 14;

        Calendar …
Run Code Online (Sandbox Code Playgroud)

java random trend

11
推荐指数
1
解决办法
249
查看次数

Android WebView缓存目录(data_1,f_000001等)中的文件格式是什么?

我在WebView的帮助下创建了一个基本的浏览器.

当我访问了一个网站(包括一些文本和一些图片),在/data/data/com.mayexample/cache/webViewCacheChromium缓存目录中被充满了所谓的指数,Data_0的,数据1,数据,f_00001,f_00002等几个文件.

我想知道,这些文件的格式是什么,它们包含什么?我想"所以,这些文件中的一些肯定必须是网站的图像然后"并尝试在文件管理器中打开它们(打开图像).但无论我选择什么文件,该过程都会显示"加载失败!".即使我将其中一些重命名为.jpg,我仍然无法打开任何东西.我在互联网上看到这对某些人有用(看看 Android WebView - 从缓存加载图像,这正是我想要做的),但我对缓存的文件无能为力.

你知道打开webview缓存文件的方法吗?例如,一个文件不代表相应的缓存图像吗?

我真正想要实现的目标(一旦我理解了缓存文件的结构)就是以编程方式从它的缓存中获取webview的图像,就像上面发布的链接的作者一样(不幸的是这个帖子的答案没有多大帮助)

谢谢!

android caching file webview

6
推荐指数
1
解决办法
4162
查看次数

如何处理或测试某个类型是否是 Rust 宏中的选项?

我正在尝试创建一个宏来生成一个可以从 postgres 数据库填充的结构。现在,由于数据库中存在可为空和不可为空的字段,我希望在宏中以不同的方式处理它们。

输出应该是这样的结构:

#[derive(Debug, Default)]
pub struct MyStruct {
    pub attrib_a: i64,
    pub attrib_b: Option<i64>,
}

impl MyStruct {
    pub fn get_row(&self, row: &postgres::rows::Row) -> MyStruct {
        MyStruct {
            // the non-nullable attrib_a, where I can for sure take the value out of the Option and assign it
            attrib_a: match row.get::<_, Option<i64>>("attrib_a") {
                Some(x) => x,
                None => 0,
            },

            // here for the nullable attrib_b I just want to return the Option as is
            attrib_b: row.get::<_, Option<i64>>("attrib_b"),
        } …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

2
推荐指数
1
解决办法
1989
查看次数

使用synchronized(lock object)块时,静态锁对象是否需要是final的?

假设我有一个

private static Object lock = new Object();
Run Code Online (Sandbox Code Playgroud)

在同一个班级的某个地方

public void run() {
synchronized(lock) {
    //only 1 thread here, all others wait
  }
}
Run Code Online (Sandbox Code Playgroud)

我总是读到锁对象应该是最终的,但不知道为什么。假设我 100% 知道我的代码不会在任何地方触及锁定对象,如果省略了final关键字,这是否意味着同步不是100%防弹的

java synchronization synchronized

2
推荐指数
1
解决办法
401
查看次数