I want to run background service application and UIApplication same time.
Is it possible to create both in same project or need to create separate separate project.
Actually i am confuse in how call or start background service in Event Thread.
This is how you can set up an alternate entry point for your application:
A- Using the BlackBerry® Java® Plug-in for Eclipse®
After creating the project for the original application, create an alternate entry point to launch the application UI.
1- Double click on BlackBerry_App_Descriptor.xml within your project.
2- Check off System Module and Do not display the application icon on the BlackBerry home screen.
3-Click on the Alternate Entry Point tab.
4- Click the Add button.
5- Enter a title for the entry point and click OK.
6- Specify the application argument that would launch the application using this alternate entry point (for example: gui).
7- Proceed to the Common Steps section.
8- Modify the main() method of the original project as follows:
public static void main(String[] args) {
if ( args != null && args.length > 0 && args[0].equals("gui") ){
// code to initialize the app
theApp.enterEventDispatcher();
} else {
// code to launch the background thread }
}
}
B- Using the BlackBerry JDE
After creating the projects for the original application, you will have to create another project for the UI entry point. Assuming that the thread to be run exists in the same project as the original application, follow these steps:
1- Right-click the project node and select Properties.
2- In the Properties window, select the Application tab.
3- Verify the following options are checked: Auto-run on startup and System module (to register the thread with the system).
4- Create another project under the same folder as the original project. Right-click the new project node and select Properties.
5- Select the Application tab and select Alternate CLDC Application Entry Point from the Project type drop-down list. As shown in the attached file, select the name of the original project (for example, trafficreporter) from the Alternate entry point for drop-down list. Also specify the arguments that would launch the application using this alternate entry point (for example: gui).
Proceed to the Common Steps section.
6- Modify the main() method of the original project as follows:
public static void main(String[] args) {
if ( args != null && args.length > 0 && args[0].equals("gui") ){
// code to initialize the app
theApp.enterEventDispatcher();
} else {
// code to launch the background thread }
}
}
http://supportforums.blackberry.com/t5/Java-Development/Background-thread-for-push-notifications/td-p/563071
the Blackberry dev forums are full of threads and sample code to accomplish this very thing.
Personally, I use the alternate entry point method, run the background app as an autostart UiApplication (with no icon) that never pushes a MainScreen, but uses its own dispatch thread to throw up a dialog or similar notifications, and then when the actual Home Icon is pressed/clicked, I launch the Ui entry point to play with the user.
Related
I am looking to split up my user base to 10 group and show 10 different UI and see how they feel about it.
so each user group will have single type of UI always.
i.e Let's say I have 10k users and when I roll out my next release when user install I will be showing for 1000 user 1 UI and for another 1000 user 1 UI like all 10K users.
I know this can be done with the help of AB testing framework.
Basically I want to call one API at the launch of app and it has to return value between 1 to 10 then I can store it in my keychain and next time when app is launched I will see if it's already there in keychain and I will not call the API.
So basically the API will know how many requests has come and it'll divide and send right values back
so based on value in keychain I will show different , different UI and here AB testing framework's job would be giving me value 1 to 10 the API part.
There are so many AB testing framework available online.But I couldn't find any framework that suits my needs.
any help is appreciated !
The best approach would be splitting the users into groups in data base and let login API or some other API return some flag to indicate what group each user belongs to and you can show UI accordingly.
But if that's not possible
Then the simplest approach would be generating a random number between 1-10 and keeping it in keychain and showing a particular UI for it so that next time when you launch the app you can look out for the value in Keychain and if its not there then you can create a new random value and store it in the keychain.This way you will show the same UI for that user always.
This splitting approach is not 100% accurate but its close enough I would say
arc4random_uniform
- (NSInteger)randomNumberBetween:(NSInteger)min maxNumber:(NSInteger)max
{
return min + arc4random_uniform((uint32_t)(max - min + 1));
}
if you take sample of these random numbers 10000 times, you can see each number coming 900-1000 times which is 9-10% and its close enough
for(int i=0;i<10000;i++){
NSLog(#"random:%ld",[self randomNumberBetween:1 maxNumber:10]);
}
Seconds of Current time
you can take the seconds of current date and time and if the second is between 1-6 then you can save value 1 in keychain and for 7-12 you can save value 2 in keychain etc..54-60 you can keep value 10 in keychain.
Others
you can consider splitting the users based on Geography or country or timezone and doing this also has its own pit falls.
Like this you can devise your own strategy to split the user
but if none of the suggestions above fits your criteria then the best approach would be to look for third party AB testing frameworks but If it's going to be implemented in enterprise scale they might charge some money for it.
If I come across any such framework that provides this particular functionality alone as you asked I would update it here.
I would like to attribute the credit of this answer to this post as he has pointed out FireBase Remote Config and A/B testing.
As questioner asked I will explain the steps involved in that to achieve it.
Configuration on server
Visit https://console.firebase.google.com/ and sign in with your
google account.
Choose Create project and Click iOS
Key in app id and nick name and click register app
It'll show a link to GoogleService-Info.plist download then drag & drop it in the project
Choose Next
It'll show you Run your app to verify installation you can choose skip this step
Choose remote config from the landing page
Choose Add variable and enter a variable name of your choice but I enter ABTestVariationType and leave value empty and choose Publish changes
Choose A/B testing from the side bar then click Create Experiment then Choose Remote config
In the upcoming pop up Enter the name of your choice I enter as A/B test POC enter some description about it and that's optional anyway
In the the target users choose your app id and in the percentage of target users choose 100% and click Next then it'll show the variants section
In the variants section there will be a general category named Control group with 50% loaded by default and a variant box with 50% filled in and empty box and you can enter any name in that but I would enter variant 2.Now click add a parameter 8 times now you can see each variant has 10% and name all the variants and I would name variant 3,variant 4 to variant 10.
In the same variants section click Add Parameter from Remote config
Now you can see the a box appearing besides each variation parameter.You can enter unique value to identify each flavour.I would enter value 1 for the first variant and 2 for the second variant like that I will finish up with value 10 for the last variant and click Next
Then goal section appears you can choose one of it but I would choose Retention(15+) days and click Review and click start experiment and in prompt that's appearing choose start again
Integrating in the app
Add the following pods in your project
pod 'Firebase/Core'
pod 'Firebase/RemoteConfig'
Drag and drop the GoogleService-Info.plist that was downloaded during the server configuration
Initiate the firebase with following boiler-plate code
#import Firebase;
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions(NSDictionary *)launchOptions
{
[FIRApp configure];
return YES;
}
4.Have the class RcValues which is another boiler-plate code in your project
#import "RcValues.h"
#import Firebase;
#implementation RcValues
+(RcValues *)sharedInstance
{
static RcValues *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[RcValues alloc] init];
});
return sharedInstance;
}
-(id)init{
self=[super init];
if(self)
{
[self AcivateDebugMode];
[self LoadDefaultValues];
[self FetchCloudValues];
}
return self;
}
-(void)LoadDefaultValues
{
[FIRRemoteConfig.remoteConfigsetDefaults:
#{#"appPrimaryColor":#"#FBB03B"}];
}
-(void)FetchCloudValues
{
NSTimeInterval fetchInterval=0;
[FIRRemoteConfig.remoteConfigfetchWithExpirationDuration:
fetchInterval completionHandler:^(FIRRemoteConfigFetchStatus
status, NSError *_Nullable error)
{
NSLog(#"error:%#",error);
[FIRRemoteConfig.remoteConfig activateFetched];
}];
}
-(void)AcivateDebugMode{ //
FIRRemoteConfig.remoteConfig.configSettings=debugSettings;
FIRRemoteConfigSettings *config = [[FIRRemoteConfigSettings alloc] initWithDeveloperModeEnabled:YES];
FIRRemoteConfig.remoteConfig.configSettings=config;
}
#end
5.Invoke the class in appdelegate didFinishinglaunchoptions
RcValues *Obj=[RcValues sharedInstance];
This will download the keyvalue for ABtesting
6.Use the below code to get the AB testing key from firebase to your app
self.flavourNumber.text=[FIRRemoteConfig.remoteConfig
configValueForKey:#"ABTestVariationType"].stringValue;
Based on the key value you can show different UI as you wish.
Firebase will take care of sending the right value and you don't have to worry about divide the users into groups by yourself.
P.S
Please follow the below tutorials for more detailed info this is just a summary and I will try to summarise or add more pictures when I have free time to make it for easier understand if possible I will try to add sample project in github and link it here
firebase-tutorial-ios-ab-testing
firebase-remote-config-tutorial-for-ios
Imagine changing fonts, colour or some values in your iOS app without submitting a new build. It's pretty easy using Remote config. This tutorial will teach you A/B testing, but before A/B testing I would recommend you to look around Remote Config.
I have the exact same issue as "Paul" posted here: Can not export audiofiles via "open in:" from Voice Memos App - no answers have yet been posted on this topic.
Essentially what I'm trying to do is simple:
After having recorded a Voice Memo on iOS, I select "Open With" and from the popup that is shown I want to be able to select my app.
I've tried everything I can think of and experimented with LSItemContentTypes without success.
Unfortunately I don't have enough reputation to comment on the existing post above, and I'm getting quite desperate for a solution to this. Any help is hugely appreciated, even just to know whether it's doable or not.
Thanks!
After some experimentation and much guidance from this blog post ( http://www.theappguruz.com/blog/share-extension-in-ios-8 ), it appears that it is possible to do this using a combination of app extensions (specifically an Action Extension) and app groups. I'll describe the first part which will enable you to get your recording from Voice Memos to your app extension. The second part -- getting the recording from the app extension to the containing app (your "main" app) -- can be done using app groups; please consult the blog post above for how to do this.
Create a new target within your project for the app extension, by selecting File > New > Target... from Xcode's menu. In the dialog box that prompts you to "Choose a template for your new target:" choose the "Action Extension" and click "Next".
CAUTION: Do not choose the "Share Extension" as is done in the blog post example above. That approach is more appropriate for sharing with another user or posting to a website.
Fill in the "Product Name:" for your Action Extension, e.g., MyActionExtension. Also, for "Action Type:" I selected "Presents User Interface" because this is the way Dropbox appears to do it. Selecting this option adds a view controller (ActionViewController) and storyboard (Maininterface.storyboard) to your app extension. The view controller is a good place to provide feedback to the user and to give the user an opportunity to rename the audio file before exporting it to your app.
Click "Finish." You will be prompted to "Activate “MyActionExtension” scheme?". Click "Activate" and this new scheme will be made active. Building it will build both the action extension and the containing app.
Click the disclosure triangle for the "MyActionExtension" folder in the Project Navigator (Cmd-0) to reveal the newly-created storyboard, ActionViewController source file(s), and Info.plist. You will need to customize these files for your needs. But for now ...
Build and run the scheme you just created. You will be prompted to "Choose an app to run:". Select "Voice Memos" from the list and click "Run". (You will probably need a physical device for this; I don't think the simulator has Voice Memos on it.) This will build and deploy your action extension (and its containing app) to your device. and then proceed to launch "Voice Memos" on your device. If you now make a recording with "Voice Memos" and then attempt to share it, you should see your action extension (with a blank icon) in the bottom row. If you don't see it there, tap on the "More" button in that row and set the switch for your action extension to "On". Tapping on your action extension will just bring up an empty view with a "Done" button. The template code looks for an image file, and finding none does nothing. We'll fix this in the next step.
Edit ActionViewController.swift to make the following changes:
6a. Add import statements for AVFoundation and AVKit near the top of the file:
// the next two imports are only necessary because (for our sample code)
// we have chosen to present and play the audio in our app extension.
// if all we are going to be doing is handing the audio file off to the
// containing app (the usual scenario), we won't need these two frameworks
// in our app extension.
import AVFoundation
import AVKit
6b. Replace the entirety of override func viewDidLoad() {...} with the following:
override func viewDidLoad() {
super.viewDidLoad()
// Get the item[s] we're handling from the extension context.
// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
print("self.extensionContext!.inputItems = (self.extensionContext!.inputItems)")
var audioFound :Bool = false
for inputItem: AnyObject in self.extensionContext!.inputItems {
let extensionItem = inputItem as! NSExtensionItem
for attachment: AnyObject in extensionItem.attachments! {
print("attachment = \(attachment)")
let itemProvider = attachment as! NSItemProvider
if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMPEG4Audio as String)
//|| itemProvider.hasItemConformingToTypeIdentifier(kUTTypeMP3 as String)
// the audio format(s) we expect to receive and that we can handle
{
itemProvider.loadItemForTypeIdentifier(kUTTypeMPEG4Audio as String,
options: nil, completionHandler: { (audioURL, error) in
NSOperationQueue.mainQueue().addOperationWithBlock {
if let audioURL = audioURL as? NSURL {
// in our sample code we just present and play the audio in our app extension
let theAVPlayer :AVPlayer = AVPlayer(URL: audioURL)
let theAVPlayerViewController :AVPlayerViewController = AVPlayerViewController()
theAVPlayerViewController.player = theAVPlayer
self.presentViewController(theAVPlayerViewController, animated: true) {
theAVPlayerViewController.player!.play()
}
}
}
})
audioFound = true
break
}
}
if (audioFound) {
break // we only handle one audio recording at a time, so stop looking for more
}
}
}
6c. Build and run as in the previous step. This time, tapping on your action extension will bring up the same view controller as before but now overlaid with the AVPlayerViewController instance containing and playing your audio recording. Also, the two print() statements I've inserted in the code should give output that looks something like the following:
self.extensionContext!.inputItems = [<NSExtensionItem: 0x127d54790> - userInfo: {
NSExtensionItemAttachmentsKey = (
"<NSItemProvider: 0x127d533c0> {types = (\n \"public.file-url\",\n \"com.apple.m4a-audio\"\n)}"
);
}]
attachment = <NSItemProvider: 0x127d533c0> {types = (
"public.file-url",
"com.apple.m4a-audio"
)}
Make the following changes to the action extension's Info.plist file:
7a. The Bundle display name defaults to whatever name you gave your action extension (MyActionExtension in this example). You might wish to change this to Save to MyApp. (By way of comparison, Dropbox uses Save to Dropbox.)
7b. Insert a line for the key CFBundleIconFile and set it to Type String (2nd column), and set its value to MyActionIcon or some such. You will then need to provide the corresponding 5 icon files. In our example, these would be: MyActionIcon.png, MyActionIcon#2x.png, MyActionIcon#3x.png, MyActionIcon~ipad.png, and MyActionIcon#2x~ipad.png. (These icons should be 60x60 points for iphone and 76x76 points for ipad. Only the alpha channel is used to determine which pixels are gray, the RGB channels are ignored.) Add these icon files to your app extension's bundle, NOT the containing app's bundle.
7c. At some point you will need to set the value for the key NSExtension > NSExtensionAttributes > NSExtensionActivationRule to something other than TRUEPREDICATE. If you want your action extension to only be activated for audio files, and not for video files, pdf files, etc., this is where you would specify such a predicate.
The above takes care of getting the audio recording from Voice Memos to your app extension. Below is an outline of how to get the audio recording from the app extension to the containing app. (I'll flesh it out later, time permitting.) This blog post ( http://www.theappguruz.com/blog/ios8-app-groups ) might also be useful.
Set up your app to use App Groups. Open the Project Navigator (Cmd-0) and click on the first line to show your project and targets. Select the target for your app, click on the "Capabilities" tab, look for the App Groups capability, and set its switch to "On". Once the various entitlements have been added, click on the "+" sign to add your App Group, giving it a name like group.com.mycompany.myapp.sharedcontainer. (It must begin with group. and should probably use some form of reverse-DNS naming.)
Repeat the above for your app extension's target, giving it the same name as above (group.com.mycompany.myapp.sharedcontainer).
Now you can write the url of the audio recording to the app group's shared container from the app extension side. In ActionViewController.swift, replace the code fragment that instantiates and presents the AVPlayerViewController with the following:
let sharedContainerDefaults = NSUserDefaults.init(suiteName:
"group.com.mycompany.myapp.sharedcontainer") // must match the name chosen above
sharedContainerDefaults?.setURL(audioURL, forKey: "SharedAudioURLKey")
sharedContainerDefaults?.synchronize()
Similarly, you can read the url of the audio recording from the containing app's side using something like this:
let sharedContainerDefaults = NSUserDefaults.init(suiteName:
"group.com.mycompany.myapp.sharedcontainer") // must match the name chosen above
let audioURL :NSURL? = sharedContainerDefaults?.URLForKey("SharedAudioURLKey")
From here, you can copy the audio file into your app's sandbox, e.g., your app's Documents directory or your app's NSTemporaryDiretory(). Read this blog post ( http://www.atomicbird.com/blog/sharing-with-app-extensions ) for ideas on how to do this in a coordinated fashion using NSFileCoordinator.
References:
Creating an App Extension
Sharing Data with Your Containing App
I have a Unity UI's input field and a text box. When I use Input.GetKeyDown (KeyCode.Return), it only works on the OS X and PC build and not on the iOS build. iOS keyboard's Return key does nothing. I have tried the events, too, but it doesn't work even then.
Somebody please tell me the solution to this problem if there is any?
While I can't think of a way to harness the return key directly on iOS, there is a way to do so with the "Submit" key using the TouchScreenKeyboard class in Unity
Specifically, it has a variable TouchScreenKeyboard.done to indicate whether the user has pressed the "Submit" (or equivalent) button on any mobile device (iOS, Android WP)
You can also check the wasCanceled variable to see whether the user canceled the input.
Example
public class TouchKeyboardExample : Monobehaviour {
private TouchScreenKeyboard touchScreenKeyboard;
private string inputText = string.Empty;
void Start () {
touchScreenKeyboard = TouchScreenKeyboard.Open(inputText, TouchScreenKeyboardType.Default);
}
void Update () {
if(touchScreenKeyboard == null)
return;
inputText = touchScreenKeyboard.text;
if(touchScreenKeyboard.done)
Debug.Log("User typed in "+inputText);
if(touchScreenKeyboard.wasCanceled)
Debug.Log("User canceled input");
}
}
I've never tried this on IOS, so I'll just guess here.
Are you using the new Unity UI that was introduced in Unity4.6 / Unity5? If so, you might want to use the UI EventSystem, which you probably have somewhere in scene already (it is being added automatically when you add new Canvas object). If you don't have it in scene, add it via menu GameObject->UI->Event System.
In the EventSystem game object, there's a component called Standalone Input Module, where you can then define Submit Button property - which is mapped to Unity's Input Manager (Edit->Project Settings->Input).
On the individual UI element (i.e. InputField in your case), you can now add EventTrigger component, which can listen to Submit event and call a custom method, even pass it some data (e.g. itself, as InputField parameter of the method).
You can also listen to many more events this way (select, hover, drag, etc).
this works fine for me (PC/Mobile), try it out
this.yourInput.onSubmit.AddListener(delegate {
if (this.yourInput.text.Length > 0)
// do something here after enter (PC) or done (mobile)
});
I'm trying to get route-me to show an offline map which is bundled or to be downloaded after app installation. I'm using route-me bindings sample project to get the work done just for now. I also use the mbtiles file from the original route-me repo's SampleMap project. I copy the file to project's root directory and set it's build action to BundleResource (that's what I thought would be appropriate). After that I changed to code to this :
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
RMDBMapSource dbSource = new RMDBMapSource ("Philadelphia.mbtiles");
MapView = new RMMapView(View.Frame, dbSource.Handle);
MapView.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
if (UIScreen.MainScreen.Scale > 1.0)
MapView.AdjustTilesForRetinaDisplay = true;
Add (MapView);
}
But no luck. App runs in the simulator but showing only a grey background nothing more. So I need someone to help me and tell me what I'm doing wrong. I need to get it done this week since next week is the deadline for project. So any help would be appreciated.
I haven't actually used offline tiles myself, but based on this thread it looks like you might need to put the RMDBMapSource into an instance of RMMapContents instead of directly into the MapView. So I'm thinking it would be something like this with Xamarin:
RMDBMapSource dbSource = new RMDBMapSource ("Philadelphia.mbtiles");
MapView = new RMMapView(View.Frame, new IntPtr());
RMMapContents contents = new RMMapContents (MapView.Handle, dbSource.Handle);
That assumes you have a wrapper binding for RMMapContents too which from the looks of it the bindings project does not have by default. You'd need to throw in a wrapper that at least defines the constructor.
This page looks like it provides similar code (in Obj-C) towards the bottom.
I have a BlackBerry UiApplication, which registers some menu items in the standard Phone and Contacts applications. I need the menu items to be registered on phone startup, ie, before my UiApplication is started.
I can achieve this if I configure my UiApplication to auto-run on startup, and register the menu items in my app initialisation code using ApplicationMenuItemRepository.
My problem is that every time my UiApplication is subsequently opened, my initialisation code is run again, and I get duplicate menu items in the Phone and Contacts app. ApplicationMenuItemRepository does not provide an API to check if they are already registered. Using a static boolean in my own code also does not help, presumably because different classloaders are used for each app instance.
Am I using the wrong approach here? Should I have a separate Application (to register Phone/Contacts menu items) and UiApplication (for my views)? That feels overly complex for my needs.
Use the Alternate Entry Point
Click on the project node.
Right click and select Properties.
In the Properties window, select the Application tab.
Ensure the following options are checked: Auto-run on startup and System module (to register the thread with the system).
Create another project under the same folder as the original project. Right click on the new project node and select Properties.
Select the Application tab and select Alternate CLDC Application Entry Point from the Project type drop down menu. As shown in the attached file, select the name of the original project (for example: trafficreporter) from the Alternate entry point for drop down menu. Also specify the arguments that would launch the application using this alternate entry point (for example: gui).
Modify the main() method of the original project as follows:
public static void main(String[] args) {
if ( args != null && args.length > 0 && args[0].equals("gui") ){
// code to initialize the app
theApp.enterEventDispatcher();
} else {
// code to launch the background thread }
}
}
Add your application iconfile to the this new "Entry Point" application and make it the ribbon icon.
Use the removeMenuItem() method when the user exits your application. it will work.
if(_serverMenuItem != null) {
ApplicationMenuItemRepository.getInstance().
removeMenuItem(ApplicationMenuItemRepository.MENUITEM_PHONE,_serverMenuItem);
}
If you want to add custom menu fields to native applications you can use a RunTime store to register you menu item and then check for it while you re-run your code :
ApplicationMenuItem ami = new ApplicationMenuItem(placement); // some placement you want to use e.g 0x35090
ApplicationMenuItemRepository amir = ApplicationMenuItemRepository.getInstance();
RuntimeStore store = RuntimeStore.getRuntimeStore(); // get the store instance
if(store.get(ApplicationMenuItemRepository.MENUITEM_CALENDAR) == null)// if object is not added only then add the item to the menu
{
try
{
store.put( ApplicationMenuItemRepository.MENUITEM_CALENDAR, ami );
}
catch(IllegalArgumentException e){}
amir.addMenuItem(ApplicationMenuItemRepository.MENUITEM_CALENDAR, ami);
}