Saturday, 4 January 2014

Keyboard on iOS - Rultech Weekly

The keyboard is present in nearly every application out there. Using the keyboard is the easiest way to provide users with a way to input alphanumeric data into applications. Trivial as it might look like in the beginning, a correct implementation of keyboard behavior can be a costly endeavor. Multiple keyboard states make it hard to implement logic that will behave correctly for all of them.
This post will cover my observations and experiences with the keyboard system in iOS. I will try to describe some basic concepts behind the keyboard notification system and take a closer look at the order in which notifications are sent.
Keyboard System
There are two main patterns across the Objective-C/Cocoa framework that give the user an idea of how the communication process between different objects functions – the delegation pattern and the notifications pattern.
The public keyboard API is built around the latter. You just inform the NSNotificationCenterobject that you want to receive some specific notifications. These notifications are later sent to you from somewhere else within the application when a specific type of event occurs.
Given that notifications are a generic pattern, there has to be a way to utilize them so they provide as much information as we want them to. Moreover, this information can be represented by a different number of objects which can, in turn, represent various types. For this particular purpose there is auserInfo property in the NSNotification class. This dictionary provides the elements listening for notifications with an additional context behind the triggering of the notification.
For keyboard notifications, we use the [NSNotificationCenter defaultCenter] method to get an instance of NSNotificationCenter class, which will be used for the notification’s registration process.
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
And that’s all you need to start receiving notifications about the appearance of the keyboard. Well, what next?
Keyboard’s Notification
To put things bluntly, the iOS keyboard can be very annoying. Despite being really simple from the user’s perspective, in multiple cases the logic of the application suffers from either the lack or the misinterpretation of the system’s notifications. Below is a list of the keyboard’s notifications present in iOS:
·       UIKeyboardWillShowNotification – notification sent when the keyboard is about to show.
·       UIKeyboardDidShowNotification – notification sent when the keyboard has just appeared.
·       UIKeyboardWillHideNotification – notification sent when the keyboard is about to hide.
·       UIKeyboardDidHideNotification – notification sent when the keyboard has just been hidden.
·       UIKeyboardWillChangeFrameNotification- notification sent when the kebyoard’s frame is about to change.
·       UIKeyboardDidChangeFrameNotification – notification sent when the keyboard’s frame has just changed.
If we take a look at the names of keyboard’s notifications it is pretty easy to think that the typical (maybe the only correct) ‘path’ for these notifications looks like this:

In fact, these two are the most common, but when defining your application logic you can’t always expect to get all these notifications in the presented order. It is entirely normal not to get some of them in specific circumstances or to get them in a different order. Since we want our applications to provide the best user experience possible, we should know about every possible order that they may have to deal with.
UserInfo Dictionary
The UserInfo property of the NSNotification class is the only (public) way to get the keyboard frame and some specific information about the keyboard’s animation. Every notification gives the developer a snapshot of the keyboard’s present or future state and allows us to update the state of the application. These are the properties of a userInfo dictionary which are passed with every keyboard notification:
·       UIKeyboardFrameBeginUserInfoKey – frame of the keyboard at the beginning of the current keyboard state change.
·       UIKeyboardFrameEndUserInfoKey – frame of the keyboard at the end of the current keyboard state change.
·       UIKeyboardAnimationDurationUserInfoKey – duration of the animation used to animate the change of the keyboard state.
·       UIKeyboardAnimationCurveUserInfoKey – animation curve used to animate the change of the keyboard’s state.
UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey are two most important and probably most commonly used elements of the userInfo dictionary. That being said, there is one important thing to remember. Coordinates ‘hidden’ behind these keys don’t take rotation factors applied to the window into account, so their values can seem be wrong. It is really important to remember to use convertRect:fromWindow or convertRect:fromView to make sure we work on proper keyboard coordinates.
The two following properties are most commonly used when we want to respond to a keyboard animation with our own animation. If we have the values for both the length of the animation’s duration and the curve used for the keyboard’s animation, we can use them to create our own animation, which will sync nicely with the keyboard’s own animation.
Responding to Notifications
Let’s imagine we have a view which is an UITableView object and its frame is equal to the screen bounds. In that particular case, the appearance of the keyboard will cause the bottom part of theUITableView content to be obscured by the keyboard frame. Moreover, the user won’t be able to scroll down to the bottom part of the content view which is put in table view. This is not the kind of experience we want to provide to our users.
We can handle this case in few different ways. The majority (if not all) of them require using keyboard notifications. We just listen for the appropriate notification and change some properties of our view hierarchy, so that user gets to see the entire content of the table view.
Earlier in this post, we added ourselves as the listeners for UIKeyboardWillShowNotificationusing the addObserver:selector:name:object method of the NSNotificationCenter class. Now, we can expand that code and add a method which will be called after the notification is received:
-(void)keyboardWillShow:(NSNotification *)notification {
    CGRect keyboardEndFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    UIViewAnimationCurve curve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
    UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
    NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect frame = CGRectInset(self.tableView.frame, 0, CGRectGetHeight(keyboardEndFrame));
    [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
       self.tableView.frame = frame;
    } completion:nil];
}
This code changes the frame of the table view so that it occupies only that part of the screen which is not hidden behind the keyboard frame. Furthermore, it changes the frame using an animation that perfectly matches the keyboard animation. The animation's duration and its curve are identical to the one used to show the keyboard, so the user shouldn't even notice any changes to the table view frame. Just don't forget to return the tableView frame to its initial state after the keyboard gets hidden!
Short Summary
After reading our introduction to the notification system, you should know how to listen for or respond to keyboard notifications, you’re well-versed in the keyboard's userInfo dictionary, and spelling the names of all of the keyboard notifications is not a problem anymore.
Well, you may think that you now know everything to properly work with a keyboard. In theory that might be true, but in practice your application can sometimes exhibit some unexpected behaviors. You still don't know the order in which notifications are sent and which of them can be absent in specific circumstances. Try to think for a moment about what will happen when there’s an external keyboard connected to the iPad? Not that obvious, isn’t it?
In the following parts of this post, I’d like to explore the notifications that occur when we change the state of the keyboard, e.g. docking the keyboard, showing the keyboard when there’s an external one connected to the device, etc. Additionally, I’ll try to take a close look at the values included in theuserInfo dictionary. Finally, I’ll provide some code that will try to encapsulate some system notifications and broadcast my own. The latter notifications will have names equivalent to the system ones but will be sent in different circumstances.
Keyboard Magic
In iOS 5, Apple added a new feature to the system keyboard. Clicking and holding the keyboard button at the bottom right corner of the keyboard brings up a popup which allows you to merge/unmerge and dock/undock you keyboard. You can even move the undocked keyboard by holding and panning the abovementioned keyboard button along the screen.

Dragging keyboard triggers UIKeyboardWillChangeFrameNotification andUIKeyboardDidChangeFrameNotification notifications. First of them is send when user starts dragging and the second one after dragging is finished. Because of the fact system doesn't know what will be value of the UIKeyboardFrameEndUserInfoKey key at the beginning of the dragging, value set for this key is equal to CGRectZero in UIKeyboardWillChangeFrameNotification's dictionary. Moreover, value of the UIKeyboardFrameBeginUserInfoKey key is equal toCGRectZero in UIKeyboardDidChangeFrameNotification.

You don't get UIKeyboardWillShowNotification and UIKeyboardDidShowNotificationnotifications when a non-standard keyboard is being shown. Hiding the keyboard doesn't triggerUIKeybardWillHideNotification and UIKeyboardDidHideNotification notifications. Still, UIKeyboardWillChangeFrameNotification andUIKeyboardDidChangeFrameNotification notifications work as expected and can be used to imitate other ones (to detect when a non-standard keyboard is being shown or hidden).
How to imitate UIKeyboardWillShowNotification and UIKeyboardDidShowNotification when showing unmerged/undocked keyboard?
1.       Check whether UIKeyboardDidChangeFrameNotification was not preceded byUIKeyboardWillShowNotification.
2.       Check whether the rectangle from userInfo's UIKeyboardFrameEndUserInfoKey is within screen bounds.
If both of these conditions are met, the keyboard will be shown in the unmerged/undocked state. Imitating UIKeyboardWillHideNotification and UIKeyboardDidHideNotificationnotifications obviously works in almost the same way, albeit with slightly different logic. You just need to switch “within” from condition no. 2 to “not within” and you’re set. Here is the code:
- (void)keyboardWillShow:(NSNotification *)notification {
    self.standardKeyboard = YES;
}
- (void)keyboardWillHide:(NSNotification *)notification  {
    self.standardKeyboard = YES;
}
- (void)keyboardDidHide:(NSNotification *)notification  {   self.standardKeyboard = NO;  }  - (void)keyboardDidShow:(NSNotification *)notification  {    self.standardKeyboard = NO; }   - (void)keyboardWillChangeFrame:(NSNotification *)notification  {    CGRect endFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];   UIWindow *window = [[[UIApplication sharedApplication] windows] firstObject];
    endFrame = [window convertRect:endFrame fromWindow:nil];
    if(CGRectContainsRect(window.frame, endFrame) && !self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardWillShowNotification object:nil userInfo:notification.userInfo];
    } else if (!self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardWillHideNotification object:nil userInfo:notification.userInfo];
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardWillChangeFrameNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidChangeFrame:(NSNotification *)notification  {
    CGRect endFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    UIWindow *window = [[[UIApplication sharedApplication] windows] firstObject];
    endFrame = [window convertRect:endFrame fromWindow:nil];
    if (CGRectContainsRect(window.frame, endFrame) && !self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidShowNotification object:nil userInfo:notification.userInfo];
    } else if (!self.standardKeyboard) {
       [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidHideNotification object:nil userInfo:notification.userInfo];
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCSKeyboardDidChangeFrameNotification object:nil userInfo:notification.userInfo];
}
Toggling Dock and Merge State
Toggling the keyboard's dock and merge states causes the notifications to be sent in slightly different order than when the keyboard’s appearing or hiding:

If we dig deeper into userInfo properties of keyboard notifications, we’ll come upon even more weirdness than we expected. When unmerging or undocking the keyboard, the value forUIKeyboardFrameEndUserInfoKey in the userInfo dictionary is different inUIKeyboardDidHideNotification than in all the other notifications. The value of this key taken from UIKeyboardDidChangeFrameNotification suggests that the keyboard will be placed either in the screen or beyond it when other notifications suggest just the opposite. Also,UIKeyboardDidChangeFrameNotification is delivered with theUIKeyboardFrameBeginUserInfoKey key of the userInfo dictionary equal to CGRectZero.
Furthermore, docking or merging results in the sending of theUIKeyboardDidChangeFrameNotification notification with the value for theUIKeyboardFrameBeginUserInfoKey key equal to CGRectZero.
Splitting/Merging When Keyboard Is Undocked
Assuming the keyboard is in an undocked state, merging and splitting the keyboard makes the notification system send notifications in the following order:

That's right - UIKeyboardDidChangeFrameNotification is sent twice although there are no differences in keyboard frames passed in the userInfo dictionary. Also, do be careful with these frames - they sometimes represent pretty useless values. UIKeyboardFrameEndUserInfoKey is equal to CGRectZero in UIKeyboardDidChangeFrameNotification andUIKeyboardFrameBeginUserInfoKey is equal to CGRectZero inUIKeyboardWillChangeFrameNotification. Why twoUIKeyboardDidChangeFrameNotification notifications? The only possible reason I found for that is captured on the screenshot underneath.
It seems that during the merging/splitting animation, there is change in the keyboard view/frame, and that’s probably the reason behind having two UIKeyboardDidChangeFrameNotificationnotifications. Just don't forget these notifications don’t always occur on a one-to-one basis!
Multiple Interface Orientations - Device Rotation
Device rotation is pretty weird when we look at it from the keyboard notification perspective. It can be really frustrating and hard to notice. Let's say your application supports multiple interface orientations and users start to rotate the device when they keyboard is displayed on the screen. What happens then? If we take a closer look at the keyboard animation which appears when we rotate the screen, we’ll quickly see that there’s nothing special to it.

But even a cursory glance at the notification logs shows us that something weird is happening. It looks like the rotation of the device makes the keyboard disappear and appear again. It’s almost imperceptible from the user’s perspective, but this notification behavior can have serious implications for the logic of the application. It looks like the easiest way to detect these notifications is to implement two templates methods of the UIViewController.
Assuming that they were implemented, this is the true order for notifications/method calls for device rotation:
1.       willRotateToInterfaceOrientation:duration: - template method
2.       UIKeyboardWillHideNotification
3.       UIKeyboardDidHideNotification
4.       UIKeyboardWillShowNotification
5.       didRotateToInterfaceOrinetation:duration: - template method
6.       UIKeyboardDidShowNotification
A simple flag set in willRotateToInterfaceOrientation:duration: (and unset indidRotateToInterfaceOrientation:) lets us ignore three out of the four notifications which appear during device rotation. The only one left is pretty easy to detect - if the keyboard is displayed and you get UIKeyboardDidShowNotification, don't do anything.
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  {
    self.interfaceRotation = YES;
}
-   (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    self.interfaceRotation = NO;
}
- (void)keyboardWillShow:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCKeyboardWillShowNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidShow:(NSNotification *)notification {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCKeyboardDidShowNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardWillHide:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCKeyboardWillHideNotification object:nil userInfo:notification.userInfo];
}
- (void)keyboardDidHide:(NSNotification *)notification  {
    if (self.interfaceRotation) {
       return;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName:MCKeyboardDidHideNotification object:nil userInfo:notification.userInfo];
}
External Keyboard
Additional changes take place when we connect an external keyboard to the iPad. In this particular case, the notification behavior depends on the inputAccessoryView property of the control which was the reason for displaying the keyboard.
Let's say we have a UITextField or UITextView object and we set its inputViewAccessoryproperty. Assuming this object becomes a first responder, the view assigned to inputAccessoryView will be displayed above the keyboard on the screen. This enables programmers to provide a customized keyboard experience to the end users of the application.
If inputAccessoryView is not present or its height is equal to 0 points, no keyboard notifications are sent. My guess is that this is because in this case, no visual changes take place in application. Otherwise, all notifications behave as expected – which means they are being sent as in the majority of cases when the keyboard is displayed or hidden in a normal (not undocked or split) state.

What about the keyboard frame when inputAccessoryView is coupled with the currently displayed keyboard? Luckily for us, frames passed through keyboard notifications seem to take the displayed input view into account. That means keyboard frames passed in the objectInfo dictionary are unions of the keyboard's frame itself and the frame of the input view. Additionally, when there is an external keyboard hooked up to the device and only the accessory view is displayed, the keyboard's frame is the union of the two abovementioned frames (although the keyboard itself is not visible).
Keyboard Visibility
Due to the fact that there are so many states in which hiding or displaying the keyboard can take place, retaining a value that would inform us whether the keyboard is currently displayed on screen or not is not that obvious (and by displayed I mean visible to the user).
The easiest solution assumes the creation of a bool property which is later updated each time the system sends a UIKeyboardDidShowNotification or UIKeyboardDidHideNotificationnotification. Although really intuitive, this solution doesn't work properly when the keyboard is either undocked or unmerged.
-(void)keyboardDidShow:(NSNotification *)notification {
    self.keyboardVisible = YES;
}
-(void)keyboardDidHide:(NSNotification *)notification {
    self.keyboardVisible = NO;
}

A better approach to this problem is to update the bool property after we receive aUIKeyboardDidChangeFrameNotofication notification. Just removeUIKeyboardFrameEndUserInfoKey from the notification's userInfo property and check whether it is contained within screen bounds.
-(void)keyboardDidChangeFrame:(NSNotification *)notification{
    CGRect endFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    UIWindow *window = [[[UIApplication sharedApplication] windows] firstObject];
    endFrame = [window convertRect:endFrame fromWindow:window];
    self.keyboardVisible = CGRectContainsRect(window.frame, endFrame);
}
Notice that we’re using the CGRectContainsRect function instead of CGRectIntersectsRect. This will ensure that the keyboardVisible property will be equal to YES only when the entire keyboard is visible, and by “entire keyboard” I mean keyboard + input accessory view. If you want this property to be equal to YES even when only the input accessory view is visible (when an external keyboard is connected to the device), use CGRectIntersectsRect instead.
Rultech Blog - wordpress
Rultech Blog - blogspot
Rultech Knowledge Base
Pro!deaClub Blog
Pro!deaClub - blogspot

Sunday, 29 December 2013

Rultech weekly

iOS News

Is your AppDelegate.m cluttered with a lot of initialization code? There is a better way to organize all that code with launchOptions parameter. Great article from Mattt on different launchOption keys and code snippets on how to use it.

We all have spent numerous hours going back and forth arranging pixels and waiting for the app to build and look for the output on simulator. Ole has worked out a way with the help of Classy, Masonry and ClassyLiveLayout to see live edits in the simulator.

Great overview of Core Bluetooth APIs and best practices. iOS 7 made some great additions to the Core Bluetooth API and with iBeacon using Bluetooth LE under the hood, Apple is surely going to make more additions to it in the future versions.

UI Dynamics is the newly added library to iOS 7 that allow you to add real-world inspired interactions to your UI. Mehfuz Hossein step-by-step shows how to create a simple slide-out menu with UI Dynamics. Definitely check it out if you havent yet used UI Dynamics in your app.

Goes without saying, debugging is the most time consuming thing we do as a programmer. XCPretty library helps you format Xcode build log so you can clearly look at the error messages rather than reading between the lines.

Design

Logo matters, it gives the first visual identity to your app. Its worth looking into logo creation from every perspective. Take a look at 11 of those perspectives in this great visual post.

Dragging things from one side of the screen to another is painful and even more so when its on a touch screen. Dave makes a good case for using touchable interface rather than drag &amp; drop.

Business and Marketing

Software Developer Dennis Reimann lists his reasons for switching to a freemium model for your apps. Interesting read which discusses the growing Freemium model and the App stores tendency to leave "demo" version of apps behind in search rankings.

When words can only go so far, its up to you to screenshot the essence of your app for the respective store. Use this guide to make sure the pictures of your app are at their best.


Android News

Ever given thought to what the programming of tomorrow will look like? An Android developer walks us through a sample of what its like to develop for Google Glass.

Want to allow users to limit your app access to certain profiles? Gabriele has written a great post on how to accomplish it. Netflix just started doing it, you should too!

If you are like me you probably hate writing tests. But its good to know your options just in case. Wiebe walks through four different functional testing frameworks in this post.

Design

When words just wont do the trick you can use this collection of icons for relaying hand motions for user navigation. Fast, functional, and free.


Cross-Platform development is sometimes considered the way to go but developing the app and designing it can be worlds apart. This post aims to eek developers into consideration regarding the vastly different UIs of the standard iOS and Android App.

Tuesday, 29 January 2013

Android: Fragments within Fragments


Fragments is something I largely ignored last time, as it was available for Honeycomb and I only had 2.x devices. Now I’ve got the phone and tablet running 4.1.1 I thought it was time to have a go. Additionally, the app I’m building has some quite complex UI so fragments was basically a requirement reading the docs.
I was building out the settings stuff first (the app needs credentials to work so I kinda had to start there), which was relatively easy. I wanted to create a setup flow, whereby when you start the app it checks if you have credentials that are valid and if not walks through the setup procedure. I was using fragments to do this, each setup page being a different fragment rendered within the whole window in the main activity.
Upon realising that I had already built a PreferenceFragment for the config settings a user had to setup at the beginning (they were easy to logically group this way) I thought I would just include that in one of the setup flow fragments and my config options would be all set up themselves. This worked rather nicely, until I got a rather nasty exception when I ran through the flow for a second time:

10-07 13:28:02.663: E/AndroidRuntime(1809): FATAL EXCEPTION: main
10-07 13:28:02.663: E/AndroidRuntime(1809): java.lang.RuntimeException: Unable to destroy activity {com.example.app/com.example.app.Base}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3273)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3291)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread.access$1200(ActivityThread.java:130)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1248)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.os.Handler.dispatchMessage(Handler.java:99)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.os.Looper.loop(Looper.java:137)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread.main(ActivityThread.java:4745)
10-07 13:28:02.663: E/AndroidRuntime(1809): at java.lang.reflect.Method.invokeNative(Native Method)
10-07 13:28:02.663: E/AndroidRuntime(1809): at java.lang.reflect.Method.invoke(Method.java:511)
10-07 13:28:02.663: E/AndroidRuntime(1809): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-07 13:28:02.663: E/AndroidRuntime(1809): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-07 13:28:02.663: E/AndroidRuntime(1809): at dalvik.system.NativeStart.main(Native Method)
10-07 13:28:02.663: E/AndroidRuntime(1809): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1280)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1291)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.BackStackRecord.commitInternal(BackStackRecord.java:548)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.BackStackRecord.commit(BackStackRecord.java:532)
10-07 13:28:02.663: E/AndroidRuntime(1809): at com.kodhus.tropics.setup.SetupCredsFragment.onDestroy(SetupCredsFragment.java:24)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:983)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1035)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1017)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1826)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.Activity.performDestroy(Activity.java:5171)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1109)
10-07 13:28:02.663: E/AndroidRuntime(1809): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3260)
10-07 13:28:02.663: E/AndroidRuntime(1809): ... 11 more
I had a Google and was surprised to find endless Stack Overflow posts saying “Fragments in fragments can’t be done”. Well I may be new to this version of Android development but that seemed a little foolish and also acted like a red flag to a bull. So I had a hunt around and it turns out it is possible to do fragments within fragments, but you just have to clean up after yourself – activities only clean up the top level fragments in them when they are closed or transitioned etc.
Thus I had a half hour of playing around trying to find the right settings, and this is the code I came up with. It goes in the onDestroy method of the middle fragment, i.e. the one that is within the activity and has another fragment within it. Note that you need to know the ID of the inner fragment for this to work.

@Override
public void onDestroy() {
Fragment fragment = getFragmentManager().findFragmentById(R.id.innerfragment);
if (fragment.isResumed()) {
getFragmentManager().beginTransaction().remove(fragment).commit();
}
super.onDestroy();
}
Some explanation: first load up the inner fragment by its ID, in this case R.id.innerfragment. Make sure this is right or you will kill the wrong thing! Next, check if it is resumed. If you don’t do this check, you will try and kill a previously killed fragment, which will barf out even worse than the problem we’re trying to solve, and a little more unpredictably at that. Finally if you have a fragment that is not removed, use the fragment manager to construct a transaction to remove it. At the end you continue the stack’s destroy method call.
Turned out to be rather a few lines of code in the end to accomplish something pretty awesome, which should be possible anyway.

Friday, 17 August 2012

Android is connected to Internet Snippet

This function will return true if you can access the internet (or false if you can't). You can change the parameter being return when roaming (read the comments).


/*
* @return boolean return true if the application can access the internet
*/
private boolean haveInternet(){
    NetworkInfo info = ((ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
    if (info==null || !info.isConnected()) {
        return false;
    }
    if (info.isRoaming()) {
        // here is the roaming option you can change it if you want to disable internet while roaming, just return false
        return true;
    }
    return true;
}

Popup Facebook

Hi friends,
ProIdeaClub is now coming up with android application known as Popup Facebook,

First Preview for all my friends !!! Please comment on this and let us know your feedback!!!!
 

 

Thinking what it is really about, Pop Facebook same as pop-up SMS but now this application is for Facebook lovers, where you don't have visit Facebook to read all your post. You will get a popup and notification where you can comment, like,dislike, share and other all functionality of Facebook without visiting the site.
Isn't this amazing?
So friends wait till we release the Pop Facebook.
Screen shots would be soon added....
Also share your ideas on what type of features should be included and what is not to be included.
Waiting for your comments...

Thursday, 17 May 2012

Wallpaper Changer

Image Image Image       Image Image

 

Want to Change Wallpaper ?

The Answer is Wallpaper Changer!!!!

Just Shaking, Unlocking Screen, or Scheduling your Phone will do the stuff, how Easy, Fast and Efficient Way is that!!!

More things that would excite you about Wallpaper Changer is that now you can select photos from Facebook and Flickr too.

Wallpaper Changer app will just do the same. Install and Select the Folder for wallpaper and forget everything. Whenever you shake your phone it will change the wallpaper for you.

Note: Long Click the Folder for Selecting.

Wallpaper Changer has many other features like change wallpaper on unlocking the screen.

Notification like

1. Vibrate on wallpaper change,

2. Notification icon in title bar for easy access to the app.

3. Adjust the shake sensitivity as per your requirement.

Most Imp.

4. Change Wallpaper on Unlocking the Screen.

5. Random Wallpaper Selection

6. Change Wallpaper on Regular Interval.

7. Start on Boot.

Wallpaper Quality can also be controlled by the user.

(HIGHER THE VALUE LOWER THE QUALITY, LOWER VALUE HIGER QUALITY)

HIGH QUALITY might take some time to change wallpaper!!!

No need to resize the images, so no space is utilized, the images are just processed for displaying as per the selected Quality.

Your Images are not Changed in any conditions.

You can preview the images using the preview button to have a view how your images would look as wallpaper.

There is no option for Landscape mode for now. So if you are looking for something like that please do not install this app.

Wallpaper Changer has added more functions like Facebook Albums, Flickr AlbumsChanging wallpaper on regular intervals, Randomly changing wallpaper.

We are surely going to add more functions like landscape mode, Picasa Albums, and many more, etc.

But our main focus is on Stability and Performance, We would really not like to integrate any feature which would ,lower the performance or stability.

Also no need to worry about rebooting your phone and turning the app On, As you can just select the option and the app will start automatically on reboot.

-----------------------------------------------------------------

Permission:

VIBRATE                               :- Vibrate Notification

RECEIVE_BOOT_COMPLETED     :- needed to start auto rotation after reboot

WRITE_EXTERNAL_STORAGE      :- Processing images for optimization, Nothing is stored on the phone or SD card.

INTERNET                            :- Send Crash Reports User Interaction is required, It will not send report by automatically.

SET_WALLPAPER_HINTS               :- Resizing the Images as per your phones screen.

-----------------------------------------------------------------

Giving Bad Reviews would not help us to resolve the issues.

As we cannot Track that. Also if the application Crashes you can send us the report to resolve it.

Or Mail us support@rultech.com for your request and issues. We will surely get back to you immediately.