Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Hat Jemand schonmal mit TestFairy herumgespielt ? (https://www.delphipraxis.net/189169-hat-jemand-schonmal-mit-testfairy-herumgespielt.html)

Rollo62 11. Mai 2016 15:07

Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Hallo Leute,

siehe oben.
Hier ist der Link dazu.

Das ist erstmal ein kostenloser Account, und kann TestFlight etc. ersetzen.
Das sieht ganz gut aus, unter Android funktioniert es,
unter iOS soll es wohl auch, aber für IOS müsste man noch Libraries einbinden damit Videos aufgenommen und
die volle Info da ist.

Ich habe nuch die folgenden Probleme damit:

Android:
- Die VideoMitschnitte werden nicht gemacht, es wird nur das StartupLogo gezeigt.
Aber dafür sieht man die gelben "Clicks" wo man hingetouch't hat.

- Jedenfalls kommen die Logs und Infos vom Tester-Gerät, CPUs Speicher, etc.
Das ist schonmal nicht schlecht.

- Wie bekomme ich auch die Videomitschnitte unter Rx10.1 hin ?

iOS:
- Das funktioniert zur Installation (ohne AppStore), und läuft auch gut.

- Nur leider kommen keine Daten, nur manuelle BugReports im Moment.

- Die SDK müsste mit in die App für InApp Systeminfo ond Videoaufnahme reinkompiliert werden.
Hat das schonmal jemand für IOS hinbekommen ?


Ansonsten scheint das echt fair und einfach zu sein.
Keine App oder sonstiger Zertifizierungskram nötig.
Einfach App hochladen auf deren Server, die stellen dann die App im Web als Download zur installation
zur Verfügung.

Würde mich freuen wenn mir mal jemand seine Erfahrung damit mitteilt.

Rollo

Rollo62 12. Mai 2016 09:47

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Ich habe mal versucht für die TfSdk ein Pascal Unit zu schreiben.

Dummerweise heisst eine Funktion darin "begin".

Gibt es eine Möglichkeit das trotzdem kompilieren zu lassen ?

Delphi-Quellcode:
type
  // non-static (instance) methods of "TfLibrary"
  IS4TfLibrary = interface(NSObject)
    ['{5875CABD-AEBA-4A91-A03F-C3DA9BFE24AD}']

    // Interface relates to name and signature in Library
    procedure begin( appToken : NSString ); cdecl;

  end;

EDIT:
Und noch eine dumme Frage:

Das SDK liegt als statische Library .a vor.
Wie sieht es denn mit iOS32 und iOS64 aus, funktioniert damit wohl beides ?


Hier die iOS Headerdatei dazu:

Code:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface TestFairy: NSObject

/**
 * Initialize a TestFairy session.
 *
 * @param appToken Your key as given to you in your TestFairy account
 */
+ (void)begin:(NSString *)appToken;

/**
 * Initialize a TestFairy session with options.
 *
 * @param appToken Your key as given to you in your TestFairy account
 * @param options A dictionary of options controlling the current session
 */
+ (void)begin:(NSString *)appToken withOptions:(NSDictionary *)options;

/**
 * Change the server endpoint for use with on-premise hosting. Please
 * contact support or sales for more information. Must be called before begin
 *
 * @param serverOverride
 */
+ (void)setServerEndpoint:(NSString *)serverOverride;

/**
 * Returns SDK version (x.x.x) string
 *
 * @return version
 */
+ (NSString *)version;

/**
 * Hides a specific view from appearing in the video generated.
 *
 * @param view The specific view you wish to hide from screenshots
 *
 */
+ (void)hideView:(UIView *)view;

/**
 * Hides a specific html element from appearing in your UIWebView
 *
 * @param selector The specific selector you wish to hide from screenshots. Multiple selectors can be comma separated
 */
+ (void)hideWebViewElements:(NSString *)selector;

/**
 * Pushes the feedback view controller. Hook a button
 * to this method to allow users to provide feedback about the current
 * session. All feedback will appear in your build report page, and in
 * the recorded session page.
 *
 */
+ (void)pushFeedbackController;

/**
 * Send a feedback on behalf of the user. Call when using a in-house
 * feedback view controller with a custom design and feel. Feedback will
 * be associated with the current session.
 *
 * @param feedbackString Feedback text
 */
+ (void)sendUserFeedback:(NSString *)feedbackString;

/**
 * Proxy didUpdateLocation delegate values and these
 * locations will appear in the recorded sessions. Useful for debugging
 * actual long/lat values against what the user sees on screen.
 *
 * @param locations Array of CLLocation. The first object of the array will determine the user location
 */
+ (void)updateLocation:(NSArray *)locations;

/**
 * Marks a checkpoint in session. Use this text to tag a session
 * with a checkpoint name. Later you can filter sessions where your
 * user passed through this checkpoint, for bettering understanding
 * user experience and behavior.
 *
 * @param name The checkpoint name
 */
+ (void)checkpoint:(NSString *)name;

/**
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 */
+ (void)setCorrelationId:(NSString *)correlationId;

/**
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 */
+ (void)identify:(NSString *)correlationId;

/**
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 * @param traits Attributes and custom attributes to be associated with this session
 */
+ (void)identify:(NSString *)correlationId traits:(NSDictionary *)traits;

/**
 * Pauses the current session. This method stops recoding of
 * the current session until resume has been called.
 *
 * @see resume
 */
+ (void)pause;

/**
 * Resumes the recording of the current session. This method
 * resumes a session after it was paused.
 *
 * @see pause
 */
+ (void)resume;

/**
 * Returns the address of the recorded session on testfairy's
 * developer portal. Will return nil if recording not yet started.
 *
 * @return session URL
 */
+ (NSString *)sessionUrl;

/**
 * Takes a screenshot.
 *
 */
+ (void)takeScreenshot;

/**
 * Remote logging, use TFLog as you would use printf. These logs will be sent to the server,
 * but will not appear in the console.
 */
#if __cplusplus
extern "C" {
#endif
   
   void TFLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
   void TFLogv(NSString *format, va_list arg_list);
   
#if __cplusplus
}
#endif

@end

extern NSString *const TFSDKIdentityTraitNameKey;
extern NSString *const TFSDKIdentityTraitEmailAddressKey;
extern NSString *const TFSDKIdentityTraitBirthdayKey;
extern NSString *const TFSDKIdentityTraitGenderKey;
extern NSString *const TFSDKIdentityTraitPhoneNumberKey;
extern NSString *const TFSDKIdentityTraitWebsiteAddressKey;
extern NSString *const TFSDKIdentityTraitAgeKey;
extern NSString *const TFSDKIdentityTraitSignupDateKey;
extern NSString *const TFSDKEnableCrashReporterKey;
extern NSString *const TestFairyDidShakeDevice;
extern NSString *const TestFairyWillProvideFeedback;
extern NSString *const TestFairyDidCancelFeedback;
extern NSString *const TestFairyDidSendFeedback;
Rollo

Sir Rufo 12. Mai 2016 09:57

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Versuch es mal bitte damit
Delphi-Quellcode:
type
  // non-static (instance) methods of "TfLibrary"
  IS4TfLibrary = interface(NSObject)
    ['{5875CABD-AEBA-4A91-A03F-C3DA9BFE24AD}']

    // Interface relates to name and signature in Library
    procedure &begin( appToken : NSString ); cdecl;

  end;

RWarnecke 12. Mai 2016 10:05

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Mal eine ganz dumme Frage, warum willst Du das SDK von TestFairy mit in die App packen ? Du kannst Apps auch ganz normal als AdHoc bei TestFairy hochladen und dann Testern zuweisen. Nur leider musst Du den Device Identifier bei Dir im Entwickler-Account registrieren. Dann klappt das ganze auch ohne TestFairy SDK.

Rollo62 12. Mai 2016 10:26

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
@Sir Rufo

Vielen Dank, das wars :thumb:

Ich Idiot habe es mit @begin probiert und bin auf die Schnelle nicht drauf gekommen ...

@RWarneke

TestFairy kann die Apps verteilen ohne das man was macht, das ist richtig.

Aber interesant wird es wenn die Screenshots mitgeliefert werden, und interne Memory und Logdaten uafgezeichnet werden.
Schau dir mal die Videos auf deren Seite an.

iOS:
Dafür muss ich wohl unter IOS diese Library und noch andere Apple.Libraries einbinden.

Android:
Unter Android habe ich die VideoScreenshots auch noch nicht am Laufen, es wird nur das Startbild
mit den simulierten TouchClicks im Video gezeigt.
Dafür werden aber schon CPU, Memory etc. als Chart aufgezeichnet.

Das sollte unter Android komplett ohne SDK funktionieren, da hast du Recht, ich vermute mal das es nicht geht
liegt daran das FMX das OS als Vectordarstellung simuliert, und nicht quasi nativ läuft.
Schade, muss ich nochmal drüber nachdenken, aber zumindest sind andere Daten mitgeloggt.


Eine ganz andere Frage zu Testfairy hätte ich, weil das ja wohl nur mit abgewandeltem Package funktionieren kann,
was dann zu denen nach Hause loggt.
Wie können die in mein APK etwas reinbauen, ohne meine Signierung ?

Bei IPA geht es wohl nicht so einfach, deswegen vermute ich mal brauchen die das SDK.

Zum Testen ist mir das noch Recht, aber für die Produktionversion muss man überlegen ob TestFairy einem da keinen Virus oder ScreenLogger mit reinbaut.
Für meine App ist das im Moment egal, aber ich würde bei sensiblen Daten vorsichtig sein.

Rollo

RWarnecke 12. Mai 2016 12:20

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Zitat:

Zitat von Rollo62 (Beitrag 1338034)
@RWarneke

TestFairy kann die Apps verteilen ohne das man was macht, das ist richtig.

Aber interesant wird es wenn die Screenshots mitgeliefert werden, und interne Memory und Logdaten uafgezeichnet werden.
Schau dir mal die Videos auf deren Seite an.

Hat da jemand Erfahrung mit, was mit einer App beim Review passiert, wenn das SDK von TestFairy noch eingebunden ist ?

Rollo62 12. Mai 2016 21:37

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Liste der Anhänge anzeigen (Anzahl: 3)
Ich bin schon ein bischen weiter damit unter iOS:

- Neues TestProjekt angelegt, auch komplett in Apple iOS und iTunes (ist vielleicht unnötig)
- Provisioning files sind angelegt, AdHoc and Distribution certificates sind da
AdHoc schein das zu sein was TestFairy-Distribution braucht
- AppStore entry ist vorbereitet, aber nicht veröffentlicht zur Prüfung
- SDK static lib ist eingebunden
- Dazu muss FMX.Platform.iOS eingebunden und gefixt werden (siehe Beispeil)
- die Library files *.a und *.h vom SDK habe ich im Beispiel s.u. nicht mit reingelegt, wegen möglicher
Lizenzprobleme (kann man von hier bekommen)
- die Library files habe ich mit ins Src Verzeichnis des Projektes gelegt (soll da statisch gelinkt werden)
- Ein call
Delphi-Quellcode:
begin("appToken");
wird direkt nach dirFinishLaunchingWithOptions aufgerufen,
mit dem AppToken von TestFairy.
- Build mit Arm7 64/32 byte dual boot code, mit richtigem Provisioning, etc.
- Debug läuft OHNE TestFairy SDK
- Release und Upload läuft MIT/OHNE TestFairy SDK
- Distribution zum Handy läuft MIT/OHNE SDK
- Installation geht nur mit AdHoc Zertifikat
- Installation geht nur auf den mit AdHoc verbundenen Devices, also maximal 100
- Programm startet MIT SDK, und crasht dann siehe Bilder unten
- Der Upload TestFairy geht, aber meldet "SDK not integrated"
- Crash passiert direkt beim Zugriff auf die statische Library
Delphi-Quellcode:
class procedure TApplicationDelegate.applicationDidFailToRegisterForRemoteNotificationsWithError(self: id; _cmd: SEL;
  application: PUIApplication; error: PNSError);
var
  Message: TPushFailToRegisterMessage;
  ErrorDescription: string;
begin
  ErrorDescription := NSStrToStr(TNSError.Wrap(error).localizedDescription);
  Message := TPushFailToRegisterMessage.Create(TPushFailToRegisterData.Create(ErrorDescription));
  TMessageManager.DefaultManager.SendMessage(nil, Message);
end;

class function TApplicationDelegate.applicationDidFinishLaunchingWithOptions(self: id; _cmd: SEL; application: PUIApplication; options: PNSDictionary): Boolean;
var
  StartupOptions: NSDictionary;
  NotificationSettings: UIUserNotificationSettings;
  LocalNotification: UILocalNotification;
  RemoteNotification: Pointer;
  WindowManager: TCocoaTouchWindowManager;
//  ITfLib : IS4TfLibrary; //Add TestFairy Library interface locally probably failed, retry

begin
  Include(FState, TApplicationDelegate.TApplicationTransitionState.Launching);
  try
    //####
    //####
    //## Here the TestFairy settings should be applied
    //##
    //## Create the interface
    //##

    ITfLib := TS4TfLibrary.Create; //!! Hier crasht es, beim Alloc:
    //##
    //## Call the interface wit hthe CORRECT appToken for SDK use
    ITfLib.&begin(StrToNSStr( '0299f3dc7.................b36fce78cb') ); //Begin TestFairy session
    //##
    //## Interface auto-destroyed
    //####
    //####

    StartupOptions := TNSDictionary.Wrap(options);
- Soweit bin ich jetzt gekommen, aber es ist schon wieder 22:30.
Deshalb habe ich das Beispiel mal angehangen, in der Hoffnung das jemand diese Library
richtig eingebunden bekommt.

Rollo

Memnarch 13. Mai 2016 11:06

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
nur mal kurz zu dem "Begin" nameclash. Dem interface ist doch der Name egal, der MethodIndex zählt. Nenns doch wie du willst ;)

Rollo62 13. Mai 2016 11:19

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Hallo Memnarch,

Die Zuordnung wird aber über den gleichen Namen gemacht.
Mir wäre auch lieber ich würde das irgendwo festlegen, statt mit CompileMagic im Hintergrund.

Ich bin mal nach Daniels super Beschreibung vorgegangen.

Aber das Interface wird nicht erzeugt.

Mir schwant aber etwas, könnte es sein das didFinishLaunchingWithOptions noch vor dem
Initialisieren des ganzen Rtti Systems getriggert wird ?
Dann könnte die Klasse eben nicht auf diese Art gefunden werden.

Gibt es einen anderen Ansatz die *.a Library von iOS har mit einer Funktion oder Klasse zu Binden,
um diese dann so früh aufzurufen ?

Rollo

mkinzler 13. Mai 2016 11:26

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Ab Berlin gibt es Unterstützung durch eine CLI-Tool.

http://www.fmxexpress.com/generate-o...delphi-berlin/

Memnarch 13. Mai 2016 11:50

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Urghs, ist das für die Mobile-Interfaces bzw bindungen zu PlatformSDKs anders o.O

Rollo62 13. Mai 2016 12:19

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
@MKinzler

Ja das hatte ich schon gesehen, scheint aber dasgleiche zu machen als das von Hand.
Schien mir komlizierter als es direkt zu versuchen.

Bin auch wieder ein stückchen weiter:

Ich hatte den Namen des Interfaces umbenannt, das macht sinn das es 1:1 gleich ist wie in der Library.
Jetzt bekomme ich jedenfalls einen ordentlichen Linioer error 00000001, aber warum weiis ich nicht.

So siehts in der Library aus, mit dem Header:

Code:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface TestFairy: NSObject

/**
 * Initialize a TestFairy session.
 *
 * @param appToken Your key as given to you in your TestFairy account
 */
+ (void)begin:(NSString *)appToken;
Das ist das Interface dazu, jetzt mit gleichen Namen.
Habe auch versucht die GUUID wegzulassen, so wie in Daniels Beispiel, ist aber immer noch mit Error.

Delphi-Quellcode:
type
  { S4TfLibrary / TS4TfLibrary }

  // non-static (instance) methods of "TfLibrary"
  TestFairy = interface(NSObject)
//    ['{5875CABD-AEBA-4A91-A03F-C3DA9BFE24AD}']

    // Interface relates to name and signature in Library
    procedure &begin( appToken : NSString ); cdecl;

  end;

  // static (class) methods of "MyLibrary"
  TestFairyClass = interface(NSObjectClass)
  end;

  TTestFairy = class(TOCGenericImport<TestFairyClass, TestFairy>)
  end;

Gelinkt wird ann mit dieser Zeile, sollte ebenfalls Daniels Beispiel entsprechen:

Delphi-Quellcode:
{$IF DEFINED(CPUARM)}
function FAKE_LOADER : TTestFairy; cdecl; external LIB_TF_LIBRARY name 'OBJC_CLASS_$_TestFairy';
{$ENDIF}


initialization
{$IF DEFINED(CPUARM)}
  /// although this code is NEVER executed, it ensures a strong reference
  ///  to the library - the linker is gonna LOVE (and consume) it!
  if FALSE then
    FAKE_LOADER;
{$ENDIF}

Die Library liegt im gleichen Verzeichnis wie die Sourcen, so definiert:
Delphi-Quellcode:
const
  LIB_TF_LIBRARY = 'libTestFairy.a';

Was kann denn jetzt noch schieflaufen ?
Ich versuche mal ein bischen die Verzeichnisse aus.

Rollo

Rollo62 13. Mai 2016 12:42

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Das Problem scheint Folgendes:

ENTWEDER ich benenne das Interface NICHT wie in der libTestFairy.a Library:

Delphi-Quellcode:

type
  { S4TfLibrary / TS4TfLibrary }
  ITestFairy = interface(NSObject)
    // Interface relates to name and signature in Library
    procedure &begin( appToken : NSString ); cdecl;
  end;


{$IF DEFINED(CPUARM)}
function FAKE_LOADER : TTestFairy; cdecl; external LIB_TF_LIBRARY name 'OBJC_CLASS_$_ITestFairy';
{$ENDIF}

Dann kann ich Kompilieren und Linken, aber beim Aufruf finder er "TestFairy" aus der Library natürlich nicht.



ODER ich benenne das Interface GENAU wie in der libTestFairy.a Library:


Delphi-Quellcode:

type
  { S4TfLibrary / TS4TfLibrary }
   TestFairy = interface(NSObject)
    // Interface relates to name and signature in Library
    procedure &begin( appToken : NSString ); cdecl;
  end;


{$IF DEFINED(CPUARM)}
function FAKE_LOADER : TTestFairy; cdecl; external LIB_TF_LIBRARY name 'OBJC_CLASS_$_TestFairy';
{$ENDIF}

Dann bekomme ich einen Linker error ...

Gibt es nochen einen Dritten Weg ?

UPDATE:
Lasse ich die Methode weg, dann kompiliert es: Juhuuuu
Aber wie komme ich das dann wieder in mein Interface rein ?
Die Signatur stimmt, nur heisst die Funktion im Orginal dummerweise "begin", könnte das Problem daher kommen ?

Code:
@interface TestFairy: NSObject

/**
 * Initialize a TestFairy session.
 *
 * @param appToken Your key as given to you in your TestFairy account
 */
+ (void)begin:(NSString *)appToken;
Delphi-Quellcode:
    // Interface relates to name and signature in Library
    procedure &begin( appToken : NSString ); cdecl;


Rollo

Rollo62 13. Mai 2016 15:23

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
@Memnarch

Die japanische Anleitung funktioniert, aber nur für das Übersetzen der SDK Frameworks.
Mag sein das es irgendwie mit eigenen *.a libraries funktioniert, muss ich noch testen.

Jedenfalls ist das schonmal OK wenn man neue SDK's einbinden will, und dazu die Pascal Units braucht.

Der Compiler wirft aber auch ein paar Fehlermeldungen raus, da habe ich jetzt keine Zeit das alles zu checken.
Ist wohl ein neuer Thread ...

EDIT:

Eine ganz blöde Idee war das libTestFairy dem SdkTransform einfach als neue Library unterzujubeln.
Also einfach ein neues Unterverzeichnis unter dem SDK anlegen, und nochmal transformieren lassen.

Dummerweise liegen die SDK's in irgendeinem Format (ohne .a) vor, also habe ich einmal beides ausprobiert.

Es kam wirklich eine Unit dabei raus, die sieht so aus:
Delphi-Quellcode:
{***********************************************************}
{                                                           }
{             CodeGear Delphi Runtime Library              }
{                                                           }
{   Copyright(c) 2012-2014 Embarcadero Technologies, Inc.  }
{                                                           }
{***********************************************************}

//
// Delphi-Objective-C Bridge
// Interfaces for Cocoa framework libTestFairy
//

unit iOSapi.libTestFairy;

interface

uses
Macapi.CoreFoundation,
Macapi.CoreServices,
Macapi.Dispatch,
Macapi.Foundation,
Macapi.Mach,
Macapi.ObjCRuntime,
Macapi.ObjectiveC,
Macapi.QuartzCore,
iOSapi.CocoaTypes,
iOSapi.Foundation;

// ===== External functions =====

const
liblibTestFairy = '/System/Library/Frameworks/libTestFairy.framework/libTestFairy';

implementation

{$IF defined(IOS) and NOT defined(CPUARM)}
uses
Posix.Dlfcn;

var
libTestFairyModule: THandle;

{$ENDIF IOS}


{$IF defined(IOS) and NOT defined(CPUARM)}
initialization
libTestFairyModule := dlopen(MarshaledAString(liblibTestFairy), RTLD_LAZY);

finalization
dlclose(libTestFairyModule);
{$ENDIF IOS}

end.
Aber da fehlt trotzdem jede Zuordnung zu den Interfaces.

Immerhin ...


Rollo

Rollo62 13. Mai 2016 15:47

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Oha, und mit ein bischen umbenennen wirft er das raus:

Delphi-Quellcode:
{***********************************************************}
{                                                           }
{             CodeGear Delphi Runtime Library              }
{                                                           }
{   Copyright(c) 2012-2014 Embarcadero Technologies, Inc.  }
{                                                           }
{***********************************************************}

//
// Delphi-Objective-C Bridge
// Interfaces for Cocoa framework libTestFairy
//

unit iOSapi.libTestFairy;

interface

uses
Macapi.CoreFoundation,
Macapi.CoreServices,
Macapi.Dispatch,
Macapi.Foundation,
Macapi.Mach,
Macapi.ObjCRuntime,
Macapi.ObjectiveC,
Macapi.QuartzCore,
iOSapi.CocoaTypes,
iOSapi.Foundation,
iOSapi.UIKit;

type

// ===== Forward declarations =====
{$M+}
TestFairy = interface;

// ===== Framework typedefs =====
{$M+}
__builtin_va_list = Pointer;
__darwin_va_list = __builtin_va_list;
// ===== Interface declarations =====

TestFairyClass = interface(NSObjectClass)
['{32B9756A-9F33-47AE-AFBD-4A25D21BD540}']
[MethodName('begin:')]
{class} procedure begin(appToken: NSString); cdecl;
{ *
 * Initialize a TestFairy session.
 *
 * @param appToken Your key as given to you in your TestFairy account
 }

[MethodName('begin:withOptions:')]
{class} procedure beginWithOptions(appToken: NSString; withOptions: NSDictionary); cdecl;
{ *
 * Initialize a TestFairy session with options.
 *
 * @param appToken Your key as given to you in your TestFairy account
 * @param options A dictionary of options controlling the current session
 }

{class} procedure setServerEndpoint(serverOverride: NSString); cdecl;
{ *
 * Change the server endpoint for use with on-premise hosting. Please
 * contact support or sales for more information. Must be called before begin
 *
 * @param serverOverride
 }

{class} function version : NSString; cdecl;
{ *
 * Returns SDK version (x.x.x) string
 *
 * @return version
 }

{class} procedure hideView(view: UIView); cdecl;
{ *
 * Hides a specific view from appearing in the video generated.
 *
 * @param view The specific view you wish to hide from screenshots
 *
 }

{class} procedure hideWebViewElements(selector: NSString); cdecl;
{ *
 * Hides a specific html element from appearing in your UIWebView
 *
 * @param selector The specific selector you wish to hide from screenshots. Multiple selectors can be comma separated
 }

{class} procedure pushFeedbackController; cdecl;
{ *
 * Pushes the feedback view controller. Hook a button
 * to this method to allow users to provide feedback about the current
 * session. All feedback will appear in your build report page, and in
 * the recorded session page.
 *
 }

{class} procedure sendUserFeedback(feedbackString: NSString); cdecl;
{ *
 * Send a feedback on behalf of the user. Call when using a in-house
 * feedback view controller with a custom design and feel. Feedback will
 * be associated with the current session.
 *
 * @param feedbackString Feedback text
 }

{class} procedure updateLocation(locations: NSArray); cdecl;
{ *
 * Proxy didUpdateLocation delegate values and these
 * locations will appear in the recorded sessions. Useful for debugging
 * actual long/lat values against what the user sees on screen.
 *
 * @param locations Array of CLLocation. The first object of the array will determine the user location
 }

{class} procedure checkpoint(name: NSString); cdecl;
{ *
 * Marks a checkpoint in session. Use this text to tag a session
 * with a checkpoint name. Later you can filter sessions where your
 * user passed through this checkpoint, for bettering understanding
 * user experience and behavior.
 *
 * @param name The checkpoint name
 }

{class} procedure setCorrelationId(correlationId: NSString); cdecl;
{ *
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 }

[MethodName('identify:')]
{class} procedure identify(correlationId: NSString); cdecl;
{ *
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 }

[MethodName('identify:traits:')]
{class} procedure identifyTraits(correlationId: NSString; traits: NSDictionary); cdecl;
{ *
 * Sets a correlation identifier for this session. This value can
 * be looked up via web dashboard. For example, setting correlation
 * to the value of the user-id after they logged in. Can be called
 * only once per session (subsequent calls will be ignored.)
 *
 * @param correlationId Id for the current session
 * @param traits Attributes and custom attributes to be associated with this session
 }

{class} procedure pause; cdecl;
{ *
 * Pauses the current session. This method stops recoding of
 * the current session until resume has been called.
 *
 * @see resume
 }

{class} procedure resume; cdecl;
{ *
 * Resumes the recording of the current session. This method
 * resumes a session after it was paused.
 *
 * @see pause
 }

{class} function sessionUrl : NSString; cdecl;
{ *
 * Returns the address of the recorded session on testfairy's
 * developer portal. Will return nil if recording not yet started.
 *
 * @return session URL
 }

{class} procedure takeScreenshot; cdecl;
{ *
 * Takes a screenshot.
 *
 }

end;
TestFairy = interface(NSObject)
['{D9486008-3B18-43B2-87EB-CFD02703D7B5}']
end;

TTestFairy = class(TOCGenericImport<TestFairyClass, TestFairy>) end;
PTestFairy = Pointer;

// ===== Exported string consts =====

function TFSDKIdentityTraitNameKey: NSString;
function TFSDKIdentityTraitEmailAddressKey: NSString;
function TFSDKIdentityTraitBirthdayKey: NSString;
function TFSDKIdentityTraitGenderKey: NSString;
function TFSDKIdentityTraitPhoneNumberKey: NSString;
function TFSDKIdentityTraitWebsiteAddressKey: NSString;
function TFSDKIdentityTraitAgeKey: NSString;
function TFSDKIdentityTraitSignupDateKey: NSString;
function TFSDKEnableCrashReporterKey: NSString;
function TestFairyDidShakeDevice: NSString;
function TestFairyWillProvideFeedback: NSString;
function TestFairyDidCancelFeedback: NSString;
function TestFairyDidSendFeedback: NSString;


// ===== External functions =====

const
liblibTestFairy = '/System/Library/Frameworks/libTestFairy.framework/libTestFairy';
procedure TFLog(format: Pointer {NSString}); cdecl; external liblibTestFairy name _PU + 'TFLog';
procedure TFLogv(format: Pointer {NSString}; arg_list: array of const); cdecl; external liblibTestFairy name _PU + 'TFLogv';


implementation

{$IF defined(IOS) and NOT defined(CPUARM)}
uses
Posix.Dlfcn;

var
libTestFairyModule: THandle;

{$ENDIF IOS}


function TFSDKIdentityTraitNameKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitNameKey');
end;

function TFSDKIdentityTraitEmailAddressKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitEmailAddressKey');
end;

function TFSDKIdentityTraitBirthdayKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitBirthdayKey');
end;

function TFSDKIdentityTraitGenderKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitGenderKey');
end;

function TFSDKIdentityTraitPhoneNumberKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitPhoneNumberKey');
end;

function TFSDKIdentityTraitWebsiteAddressKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitWebsiteAddressKey');
end;

function TFSDKIdentityTraitAgeKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitAgeKey');
end;

function TFSDKIdentityTraitSignupDateKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKIdentityTraitSignupDateKey');
end;

function TFSDKEnableCrashReporterKey: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TFSDKEnableCrashReporterKey');
end;

function TestFairyDidShakeDevice: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TestFairyDidShakeDevice');
end;

function TestFairyWillProvideFeedback: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TestFairyWillProvideFeedback');
end;

function TestFairyDidCancelFeedback: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TestFairyDidCancelFeedback');
end;

function TestFairyDidSendFeedback: NSString;
begin
  Result := CocoaNSStringConst(liblibTestFairy, 'TestFairyDidSendFeedback');
end;

{$IF defined(IOS) and NOT defined(CPUARM)}
initialization
libTestFairyModule := dlopen(MarshaledAString(liblibTestFairy), RTLD_LAZY);

finalization
dlclose(libTestFairyModule);
{$ENDIF IOS}

end.
Das sieht schon besser aus, werde ich mal Testen.

Rollo

Rollo62 13. Mai 2016 19:12

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Ich habe immer noch den Linker-Error, jetzt werfe ich bald das Handtruch.
Schliesslich brauchge ich TestFairy nur zum Debuggen und Bug-Fixen, wenn das schon selber zum Bug wird dann kann ich es auch lassen.

Hier noch ein paar Interessante Links zum Thema iOS Linikung:
http://ridingdelphi.blogspot.de/2014...-app_3169.html
https://www.youtube.com/watch?v=Yf9LxQYl5LA
http://blog.naver.com/simonsayz
https://www.youtube.com/watch?v=dX1DNQ11td8

Aber mit der konkreten Library komme ich nicht weiter.
Gibt es denn noch andere Ideen ?

Gerne auch Alternativen zu TestFairy, aber bitte bezahlbar.

Rollo

Rollo62 13. Mai 2016 21:33

AW: Hat Jemand schonmal mit TestFairy herumgespielt ?
 
Ich habe noch eine Erkenntnis:

Ich kann mit Daniels BeispielCode im Orginal arbeiten.

Nehme ich aber dieses XCode-Project und erzeuge die libMyLibrary neu dann geht es nicht mehr.
Es kommt der gleiche Linkerfehler wie bei mir jetzt.
- egal ob XCode 3.2 oder XCode 6.3 kompatibel.

Ich bin jetzt kein XCode-Experte, aber vermutlich ist da irgendetwas umgestellt worden am Binary seit 2013,
vielleicht hat jemand eine Idee ?
Und wie bringe ich das Delphi bei ?

Rollo


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz