我如何可以检测当前运行的应用从应用商店安装的? [英] How can I detect if the currently running app was installed from the app store?

查看:322
本文介绍了我如何可以检测当前运行的应用从应用商店安装的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有iOS版以编程方式检查,如果当前运行的应用从iOS应用商店安装的?这是对比的是经X code,TestFlight,或任何非官方分布源运行的应用程序。

这是在不访问应用程序的源$ C ​​$ C一个SDK的情况下。

需要明确的是 - 我找的一些签名,可以这么说,考虑到应用程序(苹果presumably),即意志,没有任何preprocessor标志或其他构建配置的依赖,可以访问在运行时的任何应用程序。


解决方案

从App Store下载的应用程序必须通过实体店增加了一个 iTunesMetadata.plist 文件:

 的NSString *文件= [NSHomeDirectory()stringByAppendingPathComponent:@iTunesMetadata.plist];
如果([的NSFileManager defaultManager] fileExistsAtPath:文件]){
    //大概商店应用
}

也许你可能要检查这个文件是否存在。

更新

在iOS8上,应用程序包已被移动。据@silyevsk,中的plist现在是一个级别[新的应用程序主束路径]以上,在/private/var/mobile/Containers/Bundle/Application/4A74359F-E6CD-44C9-925D-AC82E‌‌​​B5EA837/iTunesMetadata.plist,不幸的是,这不能从应用访问(拒绝)

更新2015年11月4日

看来,检查收到的名字可以提供帮助。必须指出的是,这种解决方案略有不同:它不返回我们是否正在运行的应用程序商店的应用程序,而是我们是否正在运行一个测试Testflight应用程序。根据您的情况下,这可能会或可能不会是有用的。

在最重要的是,它是一个非常脆弱的解决方案,因为收据名称可能随时改变。我的报告也无妨,如果你有没有其他的选择:

  //的Objective-C
BOOL isRunningTestFlightBeta =〔〔〔〔一个NSBundle mainBundle] appStoreReceiptURL] lastPathComponent] isEqualToString:@sandboxReceipt];//斯威夫特
让isRunningTestFlightBeta = NSBundle.mainBundle()。appStoreReceiptURL?.lastPathComponent ==sandboxReceipt

来源:下载检测,如果iOS应用从苹果公司的Testflight <下载/ p>

HockeyKit它是如何

通过将应用程序是否在模拟器运行,就可以猜到各种检查,在Testflight身材,或在AppStore的构建。

下面是从HockeyKit段:

  BOOL bit_isAppStoreReceiptSandbox(无效){
#如果TARGET_OS_SIMULATOR
  返回NO;
#其他
  NSURL * appStoreReceiptURL = NSBundle.mainBundle.appStoreReceiptURL;
  * NSString的= appStoreReceiptLastComponent appStoreReceiptURL.lastPathComponent;  BOOL isSandboxReceipt = [appStoreReceiptLastComponent isEqualToString:@sandboxReceipt];
  返回isSandboxReceipt;
#万一
}BOOL bit_hasEmbeddedMobileProvision(无效){
  BOOL hasEmbeddedMobileProvision = !! [一个NSBundle mainBundle] pathForResource:@嵌入ofType:@mobileprovision];
  返回hasEmbeddedMobileProvision;
}BOOL bit_isRunningInTestFlightEnvironment(无效){
#如果TARGET_OS_SIMULATOR
  返回NO;
#其他
  如果(bit_isAppStoreReceiptSandbox()及&放大器;!bit_hasEmbeddedMobileProvision()){
    返回YES;
  }
  返回NO;
#万一
}BOOL bit_isRunningInAppStoreEnvironment(无效){
#如果TARGET_OS_SIMULATOR
  返回NO;
#其他
  如果(bit_isAppStoreReceiptSandbox()|| bit_hasEmbeddedMobileProvision()){
    返回NO;
  }
  返回YES;
#万一
}BOOL bit_isRunningInAppExtension(无效){
  静态BOOL isRunningInAppExtension = NO;
  静态dispatch_once_t checkAppExtension;  dispatch_once(安培; checkAppExtension,^ {
    isRunningInAppExtension =([。APPEX /[一个NSBundle mainBundle] executablePath] rangeOfString @] =位置NSNotFound!);
  });  返回isRunningInAppExtension;
}

来源:的 GitHub的 - bitstadium / HockeySDK-IOS - BITHockeyHelper.m

一个可能的斯威夫特类的基础上,HockeyKit的类,可以是:

  //
// WhereAmIRunning.swift
// https://gist.github.com/mvarie/63455babc2d0480858da
//
// ###检测我们在一个模拟器,TestFlight测试版或App Store,建立是否正在运行###
//
//基于https://github.com/bitstadium/HockeySDK-iOS/blob/develop/Classes/BITHockeyHelper.m
//灵感来自http://stackoverflow.com/questions/18282326/how-can-i-detect-if-the-currently-running-app-was-installed-from-the-app-store
//创建者尼欧在15年4月11日。
//进口基金会类WhereAmIRunning {    // MARK:公开    FUNC isRunningInTestFlightEnvironment() - &GT;布尔{
        如果isSimulator(){
            返回false
        }其他{
            如果isAppStoreReceiptSandbox()及&放大器; !hasEmbeddedMobileProvision(){
                返回true
            }其他{
                返回false
            }
        }
    }    FUNC isRunningInAppStoreEnvironment() - &GT;布尔{
        如果isSimulator(){
            返回false
        }其他{
            如果isAppStoreReceiptSandbox()|| hasEmbeddedMobileProvision(){
                返回false
            }其他{
                返回true
            }
        }
    }    // MARK:私人    私人FUNC hasEmbeddedMobileProvision() - GT;布尔{
        如果让_ = NSBundle.mainBundle()pathForResource(嵌入,ofType:mobileprovision)。{
            返回true
        }
        返回false
    }    私人FUNC isAppStoreReceiptSandbox() - GT;布尔{
        如果isSimulator(){
            返回false
        }其他{
            如果让appStoreReceiptURL = NSBundle.mainBundle()。appStoreReceiptURL,
                让appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent
                其中,appStoreReceiptLastComponent ==sandboxReceipt{
                    返回true
            }
            返回false
        }
    }    私人FUNC isSimulator() - GT;布尔{
        #如果弓(I386)||牌坊下(x86_64)
            返回true
            #其他
            返回false
        #万一
    }}

要点: GitHub的 - mvarie / WhereAmIRunning.swift

Is there a way in iOS to programmatically check if the currently running app was installed from the iOS App Store? This is in contrast to an app that was run via Xcode, TestFlight, or any non-official distribution source.

This is in the context of an SDK that doesn't have access to the app's source code.

To be clear - I am looking for some signature, so to speak, given to the app (presumably by Apple), that will, without dependence on any preprocessor flags or other build configurations, be accessible to any application at run time.

解决方案

Apps downloaded from the App Store have a iTunesMetadata.plist file added by the store:

NSString *file=[NSHomeDirectory() stringByAppendingPathComponent:@"iTunesMetadata.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:file]) {
    // probably a store app
}

Perhaps you might want to check if this file exists.

Update:

In iOS8, the application bundle has been moved. According to @silyevsk, the plist is now one level above [the new application main bundle path], at /private/var/mobile/Containers/Bundle/Application/4A74359F-E6CD-44C9-925D-AC82E‌‌​​B5EA837/iTunesMetadata.plist, and unfortunately, this can't be accessed from the app (permission denied)

Update Nov 4th 2015:

It appears that checking the receipt name can help. It must be noted that this solution is slightly different: it doesn't return whether we're running an App Store app, but rather whether we're running a beta Testflight app. This might or might not be useful depending on your context.

On top of that, it's a very fragile solution because the receipt name could change at any time. I'm reporting it anyway, in case you have no other options:

// Objective-C
BOOL isRunningTestFlightBeta = [[[[NSBundle mainBundle] appStoreReceiptURL] lastPathComponent] isEqualToString:@"sandboxReceipt"];

// Swift
let isRunningTestFlightBeta = NSBundle.mainBundle().appStoreReceiptURL?.lastPathComponent=="sandboxReceipt"

Source: Detect if iOS App is Downloaded from Apple's Testflight

How HockeyKit does it

By combining the various checks you can guess whether the app is running in a Simulator, in a Testflight build, or in an AppStore build.

Here's a segment from HockeyKit:

BOOL bit_isAppStoreReceiptSandbox(void) {
#if TARGET_OS_SIMULATOR
  return NO;
#else
  NSURL *appStoreReceiptURL = NSBundle.mainBundle.appStoreReceiptURL;
  NSString *appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent;

  BOOL isSandboxReceipt = [appStoreReceiptLastComponent isEqualToString:@"sandboxReceipt"];
  return isSandboxReceipt;
#endif
}

BOOL bit_hasEmbeddedMobileProvision(void) {
  BOOL hasEmbeddedMobileProvision = !![[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
  return hasEmbeddedMobileProvision;
}

BOOL bit_isRunningInTestFlightEnvironment(void) {
#if TARGET_OS_SIMULATOR
  return NO;
#else
  if (bit_isAppStoreReceiptSandbox() && !bit_hasEmbeddedMobileProvision()) {
    return YES;
  }
  return NO;
#endif
}

BOOL bit_isRunningInAppStoreEnvironment(void) {
#if TARGET_OS_SIMULATOR
  return NO;
#else
  if (bit_isAppStoreReceiptSandbox() || bit_hasEmbeddedMobileProvision()) {
    return NO;
  }
  return YES;
#endif
}

BOOL bit_isRunningInAppExtension(void) {
  static BOOL isRunningInAppExtension = NO;
  static dispatch_once_t checkAppExtension;

  dispatch_once(&checkAppExtension, ^{
    isRunningInAppExtension = ([[[NSBundle mainBundle] executablePath] rangeOfString:@".appex/"].location != NSNotFound);
  });

  return isRunningInAppExtension;
}

Source: GitHub - bitstadium/HockeySDK-iOS - BITHockeyHelper.m

A possible Swift class, based on HockeyKit's class, could be:

//
//  WhereAmIRunning.swift
//  https://gist.github.com/mvarie/63455babc2d0480858da
//
//  ### Detects whether we're running in a Simulator, TestFlight Beta or App Store build ###
//
//  Based on https://github.com/bitstadium/HockeySDK-iOS/blob/develop/Classes/BITHockeyHelper.m
//  Inspired by http://stackoverflow.com/questions/18282326/how-can-i-detect-if-the-currently-running-app-was-installed-from-the-app-store
//  Created by marcantonio on 04/11/15.
//

import Foundation

class WhereAmIRunning {

    // MARK: Public

    func isRunningInTestFlightEnvironment() -> Bool{
        if isSimulator() {
            return false
        } else {
            if isAppStoreReceiptSandbox() && !hasEmbeddedMobileProvision() {
                return true
            } else {
                return false
            }
        }
    }

    func isRunningInAppStoreEnvironment() -> Bool {
        if isSimulator(){
            return false
        } else {
            if isAppStoreReceiptSandbox() || hasEmbeddedMobileProvision() {
                return false
            } else {
                return true
            }
        }
    }

    // MARK: Private

    private func hasEmbeddedMobileProvision() -> Bool{
        if let _ = NSBundle.mainBundle().pathForResource("embedded", ofType: "mobileprovision") {
            return true
        }
        return false
    }

    private func isAppStoreReceiptSandbox() -> Bool {
        if isSimulator() {
            return false
        } else {
            if let appStoreReceiptURL = NSBundle.mainBundle().appStoreReceiptURL,
                let appStoreReceiptLastComponent = appStoreReceiptURL.lastPathComponent
                where appStoreReceiptLastComponent == "sandboxReceipt" {
                    return true
            }
            return false
        }
    }

    private func isSimulator() -> Bool {
        #if arch(i386) || arch(x86_64)
            return true
            #else
            return false
        #endif
    }

}

Gist: GitHub - mvarie/WhereAmIRunning.swift

这篇关于我如何可以检测当前运行的应用从应用商店安装的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆