小编Che*_*eng的帖子

新的Voided Purchases API的用例是什么?

Google刚推出Voided Purchases API

通过Google Play Voided Purchases API,您可以撤消对与用户无效的购买相关联的应用内商品的访问权限.用户可以通过以下方式取消购买:

  • 用户请求退款.
  • 用户取消订单.
  • 订单会被退回.

但是,我对用例感到困惑.

目前,我有一个应用程序与非消费类应用内购买项目(一次性购买).

每当我的应用程序启动时,我将使用以下代码检查用户是否已购买该项目.

https://github.com/googlesamples/android-play-billing/blob/master/TrivialDrive/app/src/main/java/com/example/android/trivialdrivesample/MainActivity.java#L243

inventory.getPurchase如果用户决定取消他们的采购订单,我希望在下次应用启动期间返回null.

那么,如何Voided Purchases API适应"用户已决定取消其采购订单"的案例?

我想通过使用onQueryInventoryFinished,我们可以确定用户目前拥有哪个项目?

android

3
推荐指数
1
解决办法
2115
查看次数

git pull、docker-compose build 和 docker-compose up -da 是在空机上部署完整解决方案的好方法吗

最近,我们刚刚完成了使用 Docker 的 Web 应用程序解决方案。

https://github.com/yccheok/celery-hello-world/tree/nginx(实际解决方案托管在私有存储库中。这个例子只是快速浏览一下我们的项目结构的样子)

我们计划在其上部署时购买 1 台空 Linux 机器。未来我们可能会购买更多机器,但以目前的流量,1 台机器就足够了。

我在单台空机上部署的计划是

git pull <from private code repository>
docker-compose build
docker-compose up -d
Run Code Online (Sandbox Code Playgroud)

由于我们将在不久的将来部署到多台机器上,我想知道,这是将 docker 应用程序部署到新的空机器上的常见做法吗?

有什么我们可以从https://hub.docker.com/使用而无需我们git pull在部署阶段执行的吗?

docker docker-compose

3
推荐指数
1
解决办法
6737
查看次数

如果我使用 Firebase Messaging,在什么情况下我应该关注“防止自动初始化”

目前,我仅使用 1 个 Firebase 产品 - Firebase Messaging。(我没有使用 Firebase Analytics)

implementation 'com.google.firebase:firebase-messaging:18.0.0'
Run Code Online (Sandbox Code Playgroud)

根据https://firebase.google.com/docs/cloud-messaging/android/client#prevent-auto-init

Firebase 生成一个实例 ID,FCM 使用该 ID 生成注册令牌,Analytics 使用该 ID 进行数据收集。生成实例 ID 后,库会将标识符和配置数据上传到 Firebase。如果您希望阻止实例 ID 自动生成,请通过将这些元数据值添加到 AndroidManifest.xml 来禁用 FCM 和 Analytics 的自动初始化(您必须禁用两者):

楼上的我实在是不太明白。

我唯一的用例是

  • 呼唤FirebaseInstanceId.getInstance().getInstanceId()
  • 接收推送通知MyFirebaseMessagingService extends FirebaseMessagingService

我想知道,在什么情况下,我应该关心“防止自动初始化”,“自动初始化”有什么问题?

android firebase firebase-cloud-messaging

3
推荐指数
1
解决办法
2235
查看次数

我们应该如何决定是使用 documentDirectory 还是 applicationSupportDirectory?

我们计划存储以下用户文件

  • SQLite 文件
  • 图像文件
  • 音频文件

我们还为用户提供了将上述文件上传和下载到第三方云存储的选项。

我想知道,我们应该使用

FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
Run Code Online (Sandbox Code Playgroud)

或者

FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
Run Code Online (Sandbox Code Playgroud)

用于上述文件存储目的?

ios

3
推荐指数
2
解决办法
991
查看次数

是否有可能创建对结构数组元素的引用?

给定一个Arraystruct

    import Foundation
    
    struct Card {
        var flag: String = ""
    }
    
    var cards = Array<Card>()
    cards.append(Card())
Run Code Online (Sandbox Code Playgroud)

以下操作不会修改原始数组元素

    // A copy is created.
    var cardCopy = cards[0]
    
    // Will NOT modify cards[0] 
    cardCopy.flag = "modify0"
    
    print(cards[0].flag)
Run Code Online (Sandbox Code Playgroud)

以下操作将修改原始数组元素

    // We can modify cards[0] by
    cards[0].flag = "modify"

    print(cards[0].flag)
Run Code Online (Sandbox Code Playgroud)

然而,它在某种意义上并不高效,我们每次都需要执行索引访问。想象

    cards[0].flag0 = "modify"
    cards[0].flag1 = "modify"
    cards[0].flag2 = "modify"
    cards[0].flag3 = "modify"
    ...
Run Code Online (Sandbox Code Playgroud)

有没有办法,我们可以创建对结构数组元素的引用?这样我们就可以写

// How to create a reference to cards[0]?
var cardReference = ...
Run Code Online (Sandbox Code Playgroud)
// How …
Run Code Online (Sandbox Code Playgroud)

struct reference ios swift

3
推荐指数
1
解决办法
131
查看次数

我们什么时候应该使用 FileManager.default.urls 而不是 NSSearchPathForDirectoriesInDomains?

目前,如果我想在文档目录中创建目录层次结构,我将执行以下操作

\n
\n

使用 NSSearchPathForDirectoriesInDomains (工作正常)

\n
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)\nlet documentsDirectory = paths[0]\nlet documentUrl1 = URL(string: documentsDirectory)!\n//\n// /Users/yccheok/Library/Developer/...\n//\nprint("documentUrl1 -> \\(documentUrl1)")\n\nlet dataPath = documentUrl1.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")\nprint("dataPath.absoluteString -> \\(dataPath.absoluteString)")\nif !FileManager.default.fileExists(atPath: dataPath.absoluteString) {\n    do {\n        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: true, attributes: nil)\n        print("Folder creation done!")\n    } catch {\n        print(error.localizedDescription)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

但是,如果我使用以下

\n

使用 FileManager.default.urls (不起作用)

\n
let documentUrl0 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]\n//\n// file:///Users/yccheok/Library/Developer/...\n//\nprint("documentUrl0 -> \\(documentUrl0)")\n\nlet dataPath = documentUrl0.appendingPathComponent("SubFolder1").appendingPathComponent("SubFolder2")\nprint("dataPath.absoluteString -> \\(dataPath.absoluteString)")\nif !FileManager.default.fileExists(atPath: dataPath.absoluteString) {\n    do {\n        try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: …
Run Code Online (Sandbox Code Playgroud)

ios swift

3
推荐指数
1
解决办法
3782
查看次数

Google Play 开发者 API - 为什么当用户执行重新订阅时找不到 linkedPurchaseToken?

在我们的后端服务器中,当用户

  1. 取消订阅。
  2. 几天后再次重新订阅。

对我们来说至关重要的是,旧的购买令牌和新的购买令牌都指的是同一用户。

原因是,之前,用户已经使用旧的取消的订阅购买令牌在服务器中创建了一些数据。

当用户取消订阅并再次重新订阅时,我们希望确保用户仍然有权使用新的购买令牌访问旧数据。

我们希望可以从 获取信息linkedPurchaseToken,其中新的购买令牌将指向旧的购买令牌。

https://medium.com/androiddevelopers/implementing-linkedpurchasetoken- Correctly-to-prevent-duplicate-subscriptions-82dfbf7167da 中对此进行了描述

然而,根据我们的测试结果,情况并非如此。

Google Play 开发者 API

credentials = service_account.Credentials.from_service_account_file(
    constant.PATH_TO_SERVICE_ACCOUNT_JSON, 
    scopes = constant.SCOPES
)
    
androidpublisher = googleapiclient.discovery.build(
    'androidpublisher', 
    'v3', 
    credentials = credentials
)

product = androidpublisher.purchases().subscriptions().get(
    packageName = "com.xxx.yyy",
    subscriptionId = product_id,
    token = token
).execute()

return product
Run Code Online (Sandbox Code Playgroud)

当前活跃订阅

{
   'startTimeMillis':'1619245597271',
   'expiryTimeMillis':'1619246015249',
   'autoRenewing':True,
   'priceCurrencyCode':'SGD',
   'priceAmountMicros':'6980000',
   'countryCode':'SG',
   'developerPayload':'',
   'paymentState':1,
   'orderId':'GPA.3314-4833-2752-47988',
   'purchaseType':0,
   'acknowledgementState':1,
   'kind':'androidpublisher#subscriptionPurchase'
}
Run Code Online (Sandbox Code Playgroud)

先前取消的订阅

{
   'startTimeMillis':'1619244776697',
   'expiryTimeMillis':'1619245074590',
   'autoRenewing':False,
   'priceCurrencyCode':'SGD',
   'priceAmountMicros':'6980000',
   'countryCode':'SG',
   'developerPayload':'',
   'cancelReason':3,
   'orderId':'GPA.3358-9904-1003-13416',
   'purchaseType':0,
   'acknowledgementState':1,
   'kind':'androidpublisher#subscriptionPurchase'
} …
Run Code Online (Sandbox Code Playgroud)

android in-app-billing google-play google-play-developer-api google-play-console

3
推荐指数
1
解决办法
1858
查看次数

viewContext.setQueryGenerationFrom 试图解决 CoreData 项目中涉及事务历史记录的什么问题?

我遇到过 2 个演示 CoreData 项目,其中涉及事务历史记录。

两者都在使用

viewContext.setQueryGenerationFrom(.current)
Run Code Online (Sandbox Code Playgroud)

当他们初始化 CoreData 堆栈时。


raywenderlich 的 FireballWatch 演示

该演示摘自https://www.raywenderlich.com/14958063-modern-efficient-core-data

作者试图演示如何利用事务历史记录,在批量插入后正确更新 UI。

然而,尚不清楚viewContext.setQueryGenerationFrom(.current)试图解决什么问题。

代码: https: //github.com/yccheok/FireballWatch_Materials/blob/main/final/FireballWatch/Model/Persistence.swift#L100

文章的简要解释https://www.raywenderlich.com/14958063-modern-efficient-core-data并没有过多讲述背后的想法setQueryGenerationFrom

您通过调用 setQueryGenerationFrom(_:) 将视图上下文固定到持久存储中的最新事务。但是,由于设置查询生成仅与 SQLite 存储兼容,因此仅当 inMemory 为 false 时才执行此操作。


将本地商店从 Apple 同步到云端

该演示选自https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud

它试图演示如何使用事务历史记录来防止与 CloudKit 同步后的数据重复。

然而,目前尚不清楚viewContext.setQueryGenerationFrom(.current)要解决什么问题。

代码:https://github.com/yccheok/SynchronizingALocalStoreToTheCloud/blob/main/CoreDataCloudKitDemo/DataProvider/CoreDataStack.swift#L89

关于这个想法背后没有给出太多解释setQueryGenerationFrom


实验

无论我在 CoreData 堆栈中包含viewContext.setQueryGenerationFrom(.current)还是排除viewContext.setQueryGenerationFrom(.current),我在这两种情况下都会得到相同的观察结果。

  • NSManagedObject在我保存一个新的, 并调用后,能够立即观察 UI 更新context.save
  • NSManagedObject在我编辑现有的并调用后,能够立即观察 UI 更新context.save
  • 在我执行批处理操作后,能够立即观察 UI 更新,NSBatchUpdateRequest并 …

core-data ios swift

3
推荐指数
1
解决办法
478
查看次数

如何转发声明以下模板类

我尝试转发declare concurrent_bounded_queue;

class MyClass {
    namespace tbb {
        template<typename T> class cache_aligned_allocator;
        template<class T, class A = cache_aligned_allocator> class concurrent_bounded_queue;
    };

    // I wish to maintain this syntax.
    tbb::concurrent_bounded_queue<std::string>& concurrentBoundedQueue;
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

error C3203: 'cache_aligned_allocator' : unspecialized class template can't be used as a template argument for template parameter 'A', expected a real type
error C2955: 'tbb::cache_aligned_allocator' : use of class template requires template argument list c:\projects\vitroxreport\src\Executor.h(21) : see declaration of 'tbb::cache_aligned_allocator'
Run Code Online (Sandbox Code Playgroud)

我可以知道如何避免吗?

谢谢.

c++

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

如果找不到地图键,我可以做出以下假设吗?

std::map<std::string, int> m;
// Can I make assumption that m["NoSuchKey"] will return 0?
std::cout << m["NoSuchKey"] << std::endl;
Run Code Online (Sandbox Code Playgroud)

c++

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