我创建了一个iOS应用,并希望用户有机会免费使用该应用30天,因为该应用是第一次安装并开始。
在这30天之后,我想关闭大多数功能。保留完整功能的唯一方法是使用用户名和密码登录,用户可以在专用网站上注册。
我的问题是:
当应用程序第一次启动时,我想在远程服务器上存储此时刻的唯一标识符和时间戳。然后我就知道这个独特的身份在30天过去了。
不幸的是,似乎iOS上唯一类似uuid的标识符是identifierForVendor。根据文档,当用户从应用程序的同一供应商中删除所有应用程序然后重新安装它们时,uuid会发生变化。由于此uuid与我存储在远程服务器上的数据库中的uuid不匹配,因此用户可以在30天过后重新使用该应用程序。
来自文档:
iOS上的uuid使用identifierForVendor属性。它是独一无二的 该设备跨越同一供应商,但会因不同而不同 如果供应商的所有应用都被删除,供应商和将会改变 然后重新安装。请参阅official Apple docs。
如果从备份或iCloud恢复应用程序,UUID将是相同的 因为它保存在首选项中。用户使用旧版本 插件仍然会收到另一个生成的相同的先前UUID 意味着它将从偏好中检索。
我的问题是:
有没有办法找出自用户第一次打开应用程序以来已经过了多少天,即使他删除/重新安装了我制作的所有应用程序?
注意:由于我使用的是Phonegap / Cordova,因此欢迎与Cordova兼容的解决方案,但原生的Swift / Objective-C解决方案也可以。
答案 0 :(得分:2)
您的应用可以存储自己的唯一ID(来自服务器或可能随机生成)和/或iOS设备钥匙串中的日期戳。从设备删除应用程序时,不会清除钥匙串。
请参阅Apple的Keychain services programming guide。
答案 1 :(得分:0)
NSUbiquitousKeyValueStore怎么样?
// Use `NSUbiquitousKeyValueStore`
let iCloudKeyStore: NSUbiquitousKeyValueStore? = NSUbiquitousKeyValueStore()
let isMyAppInstalled = true
iCloudKeyStore?.setBool(isMyAppInstalled, forKey: "isMyAppInstalled")
iCloudKeyStore?.synchronize()
答案 2 :(得分:0)
如果您可以创建一个webService来捕获并在Sqlite表上存储设备ID,那么这就是解决方案:
您可以获得如下设备ID:
let DID = UIDevice.currentDevice().identifierForVendor!.UUIDString
print("Device ID is : \(DID)")
然后将此ID发送到您的webSerivce,如下所示: 在AppDelegate上放了这个:
internal static var DeviceList:[StructID] = []
然后创建一个名为StructID的Swift类,如下所示:
import Foundation
class StructID{
internal var id:Int!
internal var DevieID:String!
internal var AllowInstall:String!
internal var InstalledTime:String!
internal var InstallCount:String!
}
然后在你的FirstViewController你可以发送和存储许多数据,包括这个应用程序安装此应用程序的数量,或者第一次安装的时间是什么,或者这个ID是否使用此应用程序?或者你想要的任何东西!
let IDs = StructID()
IDs.DevieID = DID
IDs.AllowInstall = AllowInstall // <declare it yourself
IDs.InstalledTime = InstalledTime // <declare it yourself
IDs.InstallCount = InstallCount // <declare it yourself
var dictionary = Dictionary<String, AnyObject>()
dictionary["id"] = IDs.id
dictionary["DevieID"] = IDs.DevieID
dictionary["AllowInstall"] = IDs.AllowInstall
dictionary["InstalledTime"] = IDs.InstalledTime
dictionary["InstallCount"] = IDs.InstallCount
let url = NSURL(string: "http://www.YourWebAddress.com/service.php?action=insert")
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.timeoutInterval = NSTimeInterval(10)
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions(rawValue: 0))
request.HTTPBody = jsonData
} catch {
print("json data error")
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTaskWithRequest(request) { (NSData, response, error) -> Void in
let id = String (data: NSData!, encoding: NSUTF8StringEncoding)
DeviceList.id = Int(id!) // <= its id column of your table
AppDelegate.DeviceList.append(IDs) // <= it the Device id Your are sending
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.navigationController?.popToRootViewControllerAnimated(true)
})
}
task.resume()
}
和你的webService上的php代码:
function getConnection () {
$servername = "localhost";
$username = "YourDatabseName_db";
$password = "Password";
$dbname = "YourDatabseName_db";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
return $conn;
}
$action = $_GET["action"];
if ($action == "insert") {
$conn = getConnection();
$jsonString = file_get_contents('php://input');
$data = json_decode($jsonString, true);
$DeviceID = $data["DeviceID"];
$AllowInstall = $data["AllowInstall"];
$InstalledTime = $data["InstalledTime"];
$InstallCount = $data["InstallCount"];
$sql = "INSERT INTO `YourDatabase_db`.`YourTableName` (`DeviceID`, `AllowInstall`, `InstalledTime `, `InstallCount `) VALUES ('$DeviceID', '$AllowInstall', '$InstalledTime', '$InstallCount')";
if (mysqli_query($conn, $sql)){
$last_id = mysqli_insert_id($conn);
echo $last_id;
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
终于当你的应用每次亮起时,你都会检查所有的条件并做你想做的事情......
for readig从php回来把它放在你的webservice php上:
if ($action == "selectgeneral") {
$conn = getConnection();
$sql = "SELECT * FROM yourtablename";
$result = $conn->query($sql);
$output = array();
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$record = array();
$record["id"] = $row["id"];
$record["DevieID"] = $row["DevieID"];
$record["AllowInstall"] = $row["AllowInstall"];
$record["InstalledTime"] = $row["InstalledTime"];
$record["InstallCount"] = $row["InstallCount"];
array_push($output, $record);
}
} else {
echo "0 results";
}
$conn->close();
echo json_encode($output);
如果你想从你的php中读取你的数据:
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) {(NSData, response, error) -> Void in
do {
let records = try NSJSONSerialization.JSONObjectWithData(NSData!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for record in records {
let record = StructID()
record.id = Int(record["id"] as! String)
record.DevieID = record["DevieID"] as! String
record. AllowInstall = record["AllowInstall"] as! String
record.InstalledTime = Int(record["InstalledTime"] as! String)
record.InstallCount = Int(record["InstallCount"] as! String)
AppDelegate.DeviceID.append(record)
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableViewNote.reloadData()
})
}
catch {
print("Json Error")
}
}
task.resume()
抱歉,如果它有点复杂。