Cara mengetahui pada waktu proses apakah aplikasi iOS berjalan melalui penginstalan TestFlight Beta

123

Apakah mungkin untuk mendeteksi pada waktu proses bahwa aplikasi telah diinstal melalui TestFlight Beta (dikirimkan melalui iTunes Connect) vs App Store? Anda dapat mengirimkan satu app bundle dan menyediakannya melalui keduanya. Apakah ada API yang dapat mendeteksi cara mana itu dipasang? Atau apakah tanda terima berisi informasi yang memungkinkan hal ini ditentukan?

kombinatorial
sumber
4
Hanya untuk memperjelas Anda berbicara tentang pengujian beta TestFlight baru melalui iTunes Connect? Atau apakah Anda berbicara tentang kapan Anda mengunggah ke TestFlight secara langsung?
keji
Beta TestFlight baru, akan menjelaskan
kombinatorial
1
Sepertinya - [NSString containsString:] adalah tambahan ios8. Jika pengujian otomatis App Store mencoba menjalankannya di ios7, jangan lakukan. ([ReceiverURLString rangeOfString: @ "sandboxReceipt"]. location! = NSNotFound) harus melakukan triknya.
rgeorge
@rgeorge terima kasih, itu adalah kesalahan bodoh!
kombinatorial
2
Saya akan bertanya tentang pendeteksian di iOS 6 yang tidak memiliki appStoreReceiptURL, tetapi tampaknya aplikasi TestFlight hanya untuk iOS 8; jadi - [NSString containsString] mungkin baik-baik saja. Saya telah menunda pengujian beta toko aplikasi karena hal ini, tetapi saya kira beberapa orang mungkin menggunakan strategi pengujian hibrid, dengan Ad-Hoc untuk pengujian lama dan AppStore beta untuk beta publik, jadi rangeOfString masih menang.
Gordon Dove

Jawaban:

117

Untuk aplikasi yang diinstal melalui TestFlight Beta, file tanda terima dinamai StoreKit\sandboxReceiptvs biasa StoreKit\receipt. Menggunakan [NSBundle appStoreReceiptURL]Anda dapat mencari sandboxReceipt di akhir URL.

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSString *receiptURLString = [receiptURL path];
BOOL isRunningTestFlightBeta =  ([receiptURLString rangeOfString:@"sandboxReceipt"].location != NSNotFound);

Perhatikan bahwa sandboxReceiptitu juga merupakan nama file tanda terima saat menjalankan build secara lokal dan untuk build yang dijalankan di simulator.

kombinatorial
sumber
7
Seperti yang disebutkan, ini berfungsi untuk pengujian lokal pada perangkat, tetapi tidak pada simulator. Saya menambahkan sesuatu seperti #if TARGET_IPHONE_SIMULATOR isRunningInTestMode = YES; #endif Jelas, ini membutuhkan #import <TargetConditionals.h>
Gordon Dove
13
Versi [[[[NSBundle mainBundle] appStoreReceiptURL] lastPathComponent] isEqualToString:@"sandboxReceipt"]ringkas : (Benar jika menjalankan biner terdistribusi TestFlight) melalui Supertop / Haddad
Nick
2
Metode ini tidak dapat digunakan dalam paket ekstensi karena tanda terima hanya ada untuk paket host.
jeeeyul
2
Hasil pengujian iOS 8 saya StoreKit/sandboxReceiptketika diinstal sebagai build debug melalui Xcode pada perangkat atau simulator. Jadi, ini mungkin tidak secara akurat membedakan build testflight dari semua build lainnya.
pkamb
3
Tampaknya juga mengembalikan YA saat menginstal build dengan distribusi Ad Hoc.
Keller
75

Berdasarkan jawaban kombinatorial saya membuat kelas pembantu SWIFT berikut. Dengan kelas ini, Anda dapat menentukan apakah itu debug, testflight, atau build appstore.

enum AppConfiguration {
  case Debug
  case TestFlight
  case AppStore
}

struct Config {
  // This is private because the use of 'appConfiguration' is preferred.
  private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"
  
  // This can be used to add debug statements.
  static var isDebug: Bool {
    #if DEBUG
      return true
    #else
      return false
    #endif
  }

  static var appConfiguration: AppConfiguration {
    if isDebug {
      return .Debug
    } else if isTestFlight {
      return .TestFlight
    } else {
      return .AppStore
    }
  }
}

Kami menggunakan metode ini dalam proyek kami untuk menyediakan ID pelacakan atau string koneksi yang berbeda per lingkungan:

  func getURL(path: String) -> String {    
    switch (Config.appConfiguration) {
    case .Debug:
      return host + "://" + debugBaseUrl + path
    default:
      return host + "://" + baseUrl + path
    }
  }

ATAU:

  static var trackingKey: String {
    switch (Config.appConfiguration) {
    case .Debug:
      return debugKey
    case .TestFlight:
      return testflightKey
    default:
      return appstoreKey
    }
  }

UPDATE 05-02-2016: Prasyarat untuk menggunakan makro preprocessor seperti # jika DEBUG adalah menyetel beberapa Bendera Kustom Kompilator Swift. Informasi lebih lanjut dalam jawaban ini: https://stackoverflow.com/a/24112024/639227

LorenzoValentijn
sumber
1
@Urkman Pastikan Anda menyetel -D DEBUGbendera. Informasi lebih lanjut dapat ditemukan di sini .
Caleb
Thnx @Caleb, saya menambahkan lebih banyak penjelasan tentang prasyarat untuk jawabannya.
LorenzoValentijn
1
Terima kasih atas jawaban Anda, saya merasa sangat membantu! Juga baik untuk diketahui, menggunakan #if targetEnvironment(simulator)Anda menentukan apakah Anda menjalankan dalam simulator. Jadi saya memiliki opsi Simulator / TestFlight / AppStore (yang dalam kasus saya lebih disukai Debug) :-)
JeroenJK
39

Versi Swift modern, yang memperhitungkan Simulator (berdasarkan jawaban yang diterima):

private func isSimulatorOrTestFlight() -> Bool {
    guard let path = Bundle.main.appStoreReceiptURL?.path else {
        return false
    }
    return path.contains("CoreSimulator") || path.contains("sandboxReceipt")
}
Serhii Yakovenko
sumber
Senang menyertakan simulator, tetapi Anda mungkin ingin mengubah nama fungsi karena tidak lagi berlaku untuk semua kasus.
dbn
2
WOW! Berhasil! Hebat! Menampilkan TRUE untuk TestFlight dan FALSE untuk AppStore untuk build yang sama (satu build dibuat dalam satu skema dengan satu penyediaan). Sempurna! Terima kasih!
Argus
@dbn dapatkah Anda menjelaskan mengapa hal ini tidak lagi berlaku untuk semua kasus?
Ethan
1
@Ethan jawaban ini diedit setelah saya memberikan komentar saya; nama metode yang digunakan adalahisTestFlight()
dbn
6

Memperbarui

Ini tidak berfungsi lagi. Gunakan metode lain.

Jawaban asli

Ini juga berfungsi:

if NSBundle.mainBundle().pathForResource("embedded", ofType: "mobileprovision") != nil {
    // TestFlight
} else {
    // App Store (and Apple reviewers too)
}

Ditemukan di Detect jika Aplikasi iOS Diunduh dari Testflight Apple

Marián Černý
sumber
2

Saya menggunakan ekstensi Bundle+isProductiondi Swift 5.2:

import Foundation

extension Bundle {
    var isProduction: Bool {
        #if DEBUG
            return false
        #else
            guard let path = self.appStoreReceiptURL?.path else {
                return true
            }
            return !path.contains("sandboxReceipt")
        #endif
    }
}

Kemudian:

if Bundle.main.isProduction {
    // do something
}
Denis Kutlubaev
sumber
-3

Ada satu cara saya menggunakannya untuk proyek saya. Berikut langkah-langkahnya.

Di Xcode, buka setelan proyek (proyek, bukan target) dan tambahkan konfigurasi "beta" ke daftar:

masukkan deskripsi gambar di sini



Kemudian Anda perlu membuat skema baru yang akan menjalankan proyek dalam konfigurasi "beta". Untuk membuat skema, buka di sini:

masukkan deskripsi gambar di sini



Beri nama skema ini apa pun yang Anda inginkan. Anda harus mengedit pengaturan untuk skema ini. Untuk melakukan ini, ketuk di sini:

masukkan deskripsi gambar di sini



Pilih tab Arsip di mana Anda dapat memilih Build configuration

masukkan deskripsi gambar di sini



Kemudian Anda perlu menambahkan kunci Configdengan nilai $(CONFIGURATION)daftar properti info proyek seperti ini:

masukkan deskripsi gambar di sini



Maka itu hanya masalah apa yang Anda butuhkan dalam kode untuk melakukan sesuatu yang spesifik untuk beta build:

let config = Bundle.main.object(forInfoDictionaryKey: "Config") as! String
if config == "Debug" {
  // app running in debug configuration
}
else if config == "Release" {
  // app running in release configuration
}
else if config == "Beta" {
  // app running in beta configuration
}
Klemen
sumber
6
Meskipun ini adalah teknik yang membantu, teknik ini tidak menjawab pertanyaan. Biner tunggal dikirimkan ke App Store dan dapat dijalankan dari pengunduhan melalui TestFlight atau setelah pengunduhan yang disetujui setelah pengunduhan dari App Store. Pertanyaannya adalah tentang mendeteksi versi mana yang sedang berjalan.
kombinatorial
Apakah ada opsi untuk membuat 2 arsip di tempat pertama. satu untuk testflight, satu untuk toko aplikasi.
Klemen
Itu mungkin, tetapi mereka harus memiliki nomor build yang berbeda. Dan itu berarti mengelola dua build, bukan satu.
kombinatorial
ok, menurut saya itu worth it. Apalagi jika Anda menggunakan alat integrasi berkelanjutan.
Klemen
@KlemenZagar, pendekatan Anda adalah pendekatan yang terkenal dan bagus tetapi tidak menjawab pertanyaan.
Stanislav Pankevich