1

Does anyone know if it is possible to load the config.xml and qcar-resources.dat (The files that contain the marker info) from outside the app bundle?

According to the official forums and documentation, it is not. However, there is an app out there called Blippar which seems to be doing it. I extracted the app Documents folder from an iPhone backup and they seem to have a config.xml in there that has more tracking markers than the one that is in the app bundle.

How could they have done this if the QCAR SDK doesn't allow you to specify a location of the tracking files?

I tried being hacky and creating a category on NSBundle to override

  • (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext;

to return a path from the documents folder instead, but that didn't seem to work.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
tomwilson
  • 1,014
  • 10
  • 12
  • I'm facing the exactly same thing. Could you please specify a little more where you put those functions and the Swizzle? It seems to overwrite the NSBundle? Thanks a lot! –  Dec 27 '11 at 13:00
  • Just FYI to anyone looking at this, this is no longer necessary as they added support to do this in the QCAR/Viewforia SDK. – tomwilson Mar 20 '12 at 01:20

3 Answers3

2

Ok, I've solved it.

First I created a category on NSBundle, and created new implementations of pretty much every method related to loading files from the bundle, until I found the one Qualcomm are using, which is:

- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext inDirectory:(NSString *)subpath;

Once I had that, I changed my category method to be:

#define XFILPATH4DOCUMENT(_value) [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:_value]

- (NSString *)pathForResourceOverride:(NSString *)name ofType:(NSString *)ext inDirectory:(NSString *)subpath
{
    if (([name isEqualToString:@"config"] && [ext isEqualToString:@"xml"]) || ([name isEqualToString:@"qcar-resources"] && [ext isEqualToString:@"dat"]))
    {
        // OMG
        NSString *fileName = [NSString stringWithFormat:@"%@.%@", name, ext];
        NSString *path = XFILPATH4DOCUMENT(fileName);
        NSLog(@"%@", path);
        return path;
    }
    else
    {
        return [self pathForResourceOverride:name ofType:ext inDirectory:subpath];
    }
}

Then, through the magic of method swizzling:

Swizzle([NSBundle class], @selector(pathForResource:ofType:inDirectory:), @selector(pathForResourceOverride:ofType:inDirectory:));

Using this method:

#import <objc/runtime.h> 
#import <objc/message.h>

void Swizzle(Class c, SEL orig, SEL replacement)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, replacement);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, replacement, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);
}

Which I got from the answer here: Method Swizzle on iPhone device

Scary? Yes.

But it works.

Community
  • 1
  • 1
tomwilson
  • 1,014
  • 10
  • 12
0

Im currently trying to do the same thing. Your answer seems good but I have another suggestion. The API states that

enter image description here

So this means that you can load trackable data at any given moment.

If you need dynamic content then create a utility function in your app which renames the files you need as config and qcar-resources.dat. For example lets say you have 20 different config and dat files in the form of config_x.xml etc in your app bundle then you simply delete the current config and qcar-resource data files and copy and rename the files you want to be used. Then you can call QCAR::Tracker::load() and it will load those files for you. This is considerably safer than your method which is really a hack and not a solution.

twerdster
  • 4,977
  • 3
  • 40
  • 70
  • load only seems to load config.xml and qcar-resources.dat from the app bundle though? And you can't delete or rename files in your app bundle? – tomwilson Nov 17 '11 at 22:45
  • you said in your question that Blippar had a different config file in their documents folder so doesnt that mean they are getting the data from there? – twerdster Nov 17 '11 at 23:06
  • Yes, but that is the whole problem I was trying to solve - how to get QCAR to load from the documents folder instead of the app bundle. As you can update the documents folder at run time, the bundle you cannot. – tomwilson Nov 17 '11 at 23:18
  • In that case your answer is the only valid answer. Nice work by the way! – twerdster Nov 18 '11 at 00:43
0

QCAR SDK 1.5 Beta now supports swapping datasets at runtime! :) Download

Oli
  • 1,407
  • 3
  • 30
  • 47