How to use iOS 5+ AirPlay for a second screen - ios5

I'm toying with AirPlay using an iPhone 4S and I'm having some trouble. I've updated my Apple TV 2 to the latest (4.4.3 I think? I forget, it's in the other room and I'm too lazy to check) and I have iOS 5.0 on my 4S while I use Xcode 4.2 Build 4D199. I wrote a simple UIView app that attempts to draw on a second screen when available. Here's what I have in my viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:[[MPVolumeView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)]];
NSLog(#"Registering for screen connect events...");
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(screenDidConnect:)
name:UIScreenDidConnectNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(screenDidDisconnect:)
name:UIScreenDidDisconnectNotification
object:nil]; NSLog(#"There are %i connected screens.", ScreenCount);
if (ScreenCount > 1) {
self.secondWindow = [self myScreenInit:[[UIScreen screens] objectAtIndex:1]];
[self.secondWindow addSubview:[self createFullscreenViewForText:#"Second window" withSize:CGSizeMake(640, 480)]];
}
}
This code works in the simulator when I enable TV Out although it always crashes if I enable TV Out while in debug. I have to relaunch the app after enabling TV out in the hardware menu in the simulator. On relaunch I see the second screen UILabel on the second screen. On the iPhone 4S I can only make this work if I enable AirPlay using the AirPlay control in the running tasks bar all the way to the left. You'll note that I have added an MPVolumeView component to the view on launch which I attempt to use to connect to my Apple TV to no avail.
If I use the in app MPVolumeView I can successfully disconnect from the Apple TV but when I use it again and select the apple TV to reconnect I do not get the UIScreenDidConnectNotification. Again the only time I can see the 2nd screen is when I enable mirroring. If I connect with either AirPlay control I only count 1 screen and never get the notification. Also, each time I enable mirroring I see this in the console logs:
Could not find mapped image ColorOnGrayShadow_AirPlay.png
This seems to be broken and I would like to know what others experience has been in this area. I'll continue to toy around and update this post as I learn new things.

MPVolumeView's route menu can only control an audio stream going to the AppleTV.
Here's a working example of what you are trying to do:
https://github.com/quellish/AirplayDemo/
The "ColorOnGrayShadow_AirPlay.png" log message is normal for iOS 5. Using an Airplay connected AppleTV as an external display unfortunately requires mirroring, and you can't activate that from inside your app. The user has to follow these instructions:
http://support.apple.com/kb/TS4085

Related

Detect lock event on iOS7

Greetings for the Day Everyone!!
I want iOS devices with iOS7 version to detect the lock. I did research a lot in it, but didn't find any solution for iOS7.
For Example,
Programmatically lock iPhone screen in iOS 7
Lock Unlock events iphone
I have implemented the same feature for iOS6 but it is not working for iOS7.
Checkout the working snipppet for iOS6
// coming back in the foreground
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note)
{
// if user lock the screen
if ([[UIApplication sharedApplication] applicationState] == 1)
{
// coming back after unlocking screen..
}
}];
I have gone through many sources and found there isn't any solution for this in iOS7. Therefor I post the individual question over here, let me know if any one knows how to detect lock event on iOS7 enabled device.
Any help will be appreciated!

Responding to MPMoviePlayerController notifications during background media playback

I have an app that streams video from the net and plays it using an MPMoviePlayerController object for playback on the device or via AirPlay.
The app supports background operation and has the 'audio' option listed within the required UIBackgroundModes key in its plist file.
When playing over AirPlay, the app can successfully be pushed to the background and the video continues to play properly. So far, so good.
According to the Apple documentation:
Including the audio key tells the system frameworks that they should
continue playing and make the necessary callbacks to the app at
appropriate intervals. If the app does not include this key, any audio
being played by the app stops when the app moves to the background.
However, these callbacks are not being made.
The app uses two types of callback: those associated with notifications MPMoviePlayerController and AVPlayer send during playback together with timer based callbacks that monitor the playback position and performance stats for monitoring purposes.
Looking at Apple's notes, I would certainly expect to receive the first type of callback so that the app can respond to MPMoviePlayerPlaybackStateDidChangeNotification, MPMoviePlayerPlaybackDidFinishNotification and MPMoviePlayerLoadStateDidChangeNotification, but this doesn't happen.
Does anyone know if it is possible to receive these during background AirPlay playback and, if so, how was this achieved?
**Please note: the app works correctly when running in the foreground and receives the notifications fine. It is only when pushed to the background and playing over AirPlay that the notifications are not received.
Likewise, the video plays over AirPlay in the background properly. It is only the notifications which are not received**
I had this issue and have fixed it though it was a few months back. I could send you my entire class for movie playback if this doesn't work. Note it is using the navigation controller model.
NOTE: This is tested on iPad 2 not on the iPhone.
I show my VC like this:
- (IBAction)playMovie:(id)sender {
MovieVC* movController = [[MovieVC alloc] initWithID:2];
movController.view.backgroundColor = [UIColor blackColor];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[appDel.navigationController pushViewController:movController animated:NO];
[movController release];
}
Then in my MovieVC view controller class i set up the video playback like this:
- (void)initMoviePlayer {
mMoviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[self getMovieURL]];
mMoviePlayer.allowsAirPlay = YES;
mMoviePlayer.view.frame = [self.view bounds];
mMoviePlayer.view.backgroundColor = [UIColor clearColor];
mMoviePlayer.shouldAutoplay = YES;
mMoviePlayer.fullscreen = YES;
mMoviePlayer.scalingMode = MPMovieScalingModeAspectFit;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePreloadDidFinish:)
name:MPMoviePlayerLoadStateDidChangeNotification
object:mMoviePlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:nil];
}
This fixed it for me, if it doesn't fix comment and ill edit with the entire class file.
In one of my projects I did what you did, and it worked for me.
Two differences in my project :
I am not streaming via airPlay (device playback only),
I am just playing audio files.
My step-by-step :
Add the audio option to UIBackgroundModes in the plist file,
Register to the NotificationCenter for MPMoviePlayerPlaybackDidFinishNotification and MPMoviePlayerPlaybackStateDidChangeNotification with the following code :
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(playbackStateChanged:)
name:MPMoviePlayerPlaybackStateDidChangeNotification
object:moviePlayer];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(playbackEnded:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
It works like a charm.
For completeness, I ought to add that at present I believe there is no solution to this problem.
I've discussed it directly with Apple via tech support and there was no practical work-around available.
This functionality was needed to allow the app to record stats about the playback of the stream at regular intervals. While this is fine when the video is played on the device's screen and over AirPlay while the app is in the foreground, it isn't possible to do with the app in the background.
The solution I've gone with instead is to disable the idle timer during all types of playback and to re-enable afterwards using:
[UIApplication sharedApplication].idleTimerDisabled = YES;
and
[UIApplication sharedApplication].idleTimerDisabled = NO;
While this isn't a solution to the original question, it's a workaround for avoiding the issue in the first place.

Prevent iPhone from locking when connected to charger and app is running

I'm writing an iPhone app. When the app is running and the iPhone is charging, there is no need to lock the iPhone. Is it possible to prevent the locking of the iPhone when the device is charging and my app is running?
You can subscribe to UIDeviceBatteryStateDidChangeNotification notification to get the moment when your iphone begins/stops to charge. Then in case iphone is charging you can set idleTimerDisabled property in UIApplication object to YES to prevent device to go to sleep:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateBatteryState:)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
- (void) updateBatteryState:(NSNotification*)notification{
[UIApplication sharedApplication].idleTimerDisabled =
([UIDevice currentDevice].batteryState == UIDeviceBatteryStateCharging);
}
P.S. If user decides to put device to sleep with sleep/wake button there's no way to prevent him of doing so
This is not possible with current SDK.
EDIT: hmm, haven't got the question correctly from the first read - look on other replies for correct answer; my guess was, you were asking about if it possible to prevent appearance of the sync/charge screen when connecting device via usb or to the wall outlet

Show iPhone soft keyboard even though a hardware keyboard is connected

My iPad app uses an external "device" that acts as a hardware keyboard. But, at some point in the settings, I need to input text and I can't use the "device" ("device" is not a keyboard).
So, is there any way to force pop the soft keyboard even thought I have a hardware keyboard connected?
Yes. We've done this in a few of our apps for when the user has a Bluetooth scanner "keyboard" paired with the device. What you can do is make sure your textField has an inputAccessoryView and then force the frame of the inputAccessoryView yourself. This will cause the keyboard to display on screen.
We added the following two functions to our AppDelegate. The 'inputAccessoryView' variable is a UIView* we have declared in our app delegate:
//This function responds to all textFieldBegan editing
// we need to add an accessory view and use that to force the keyboards frame
// this way the keyboard appears when the scanner is attached
-(void) textFieldBegan: (NSNotification *) theNotification
{
UITextField *theTextField = [theNotification object];
// NSLog(#"textFieldBegan: %#", theTextField);
if (!inputAccessoryView) {
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, navigationController.view.frame.size.width, 1)];
}
theTextField.inputAccessoryView = inputAccessoryView;
[self performSelector:#selector(forceKeyboard) withObject:nil afterDelay:0];
}
//Change the inputAccessoryView frame - this is correct for portrait, use a different
// frame for landscape
-(void) forceKeyboard
{
inputAccessoryView.superview.frame = CGRectMake(0, 759, 768, 265);
}
Then in our applicationDidFinishLaunching we added this notification observer so we would get an event anytime a text field began editing
//Setup the textFieldNotifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFieldBegan:) name:UITextFieldTextDidBeginEditingNotification object:nil];
Hope that helps!
There’s no way to do this with the current SDK. Please let Apple know via the Bug Reporter.
The solutions here didn't work on iOS 13 or aren't App Store compatible so I solved the problem by creating my own soft keyboard. It is pretty basic but works. Feel free to contribute!
Project on Github
All you have to do is add SoftKeyboardView.swift to your project and somewhere (e.g. appDidFinishLaunching) hit the singleton:
Usage:
SoftKeyboardManager.shared.disabled = false
Since I have the same problem, the closest solution I have found is to use Erica Sadun's app called KeysPlease which is available via cydia and modmyi. It's description is "Use soft kb even when connected to a BT kb.".
Additionally I have found that if you have a physical keyboard also attached, in my case via the iPad keyboard doc, you can bring up the keyboard using a key which seems to map to the eject key on a bluetooth keyboard. Perhaps there is a way to inject this key as if it was pressed on an attached keyboard?
I really wish there was a more official coding solution to this.
When my app connect bluetooth device, keyboard wouldn't show.I try set force the frame of the inputAccessoryView as Brian Robbins say. It didn't work.
Then I use a stupid way to solve.I found when I click textfield or textview one more time, keyboard will show.
So I just need to simulate touch in textfield or textview once , it works.
If you want to do some simulate touch, check this.
https://github.com/HUYU2048/PTFakeTouch

iPad rotation bug when using MPMoviePlayerViewController

Issue summary
Changing the orientation of an iPad device or simulator while playing a video using MPMoviePlayerViewController results in an inconsistent rotation state upon dismissal of the video player. This is a known bug in iPad SDK 3.2, documented at http://www.openradar.me/8012810
Sample project
I have prepared a minimal sample project using the View-based Application template from Xcode 3.2.2, using the following code to launch the player
NSURL *movieUrl = [NSURL URLWithString:#"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"];
MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:movieUrl];
[self presentMoviePlayerViewControllerAnimated:player];
[player release];
The code is available on GitHub at http://github.com/adamalex/FullScreenMovie or direct download using http://github.com/adamalex/FullScreenMovie/zipball/master
Steps to reproduce
Obtain the project using the information above
Launch the project with the iPad simulator or device
Tap the button to begin playing the video
Rotate the iPad by 90 degrees
Dismiss the video
Note the UIStatusBar is out of sync with the application UI
Objective
I have contacted Apple and they have confirmed this is a bug that is being investigated. I would like to discuss temporary workarounds that use public APIs safe for submission to the App Store. I am going to open a developer support case with Apple as well and will report back with my own progress.
Successful response from Apple Developer Technical Support!
This is a known bug and a we're received a number of duplicate bug reports and so iOS engineering is aware of the issue and we do have a temporary workaround as suggested by iOS engineering.
You will need to implement this in the view controller which presents the movie player.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self performSelector:#selector(fixStatusBar) withObject:nil afterDelay:0];
}
- (void)fixStatusBar {
[[UIApplication sharedApplication] setStatusBarOrientation:[self interfaceOrientation] animated:NO];
}
While this is somewhat ugly, it should fix the issue for now. It would be recommended to remove this code once the bug is fixed in the system.
This took care of the issue completely for me, and you can revisit http://github.com/adamalex/FullScreenMovie for the code with the fix applied.
This also solves an iPhone/iPodTouch rotation issue that I was struggling with. I am developing a universal app in which each view displays a different image depending on whether the device is in portrait or landscape orientation. Buttons are used to navigate between views.
If the app is running on the device and a portrait view is rotated to landscape, my image switching takes place. If the device is then placed flat on a table top and the button is tapped to display the next view, the view appears in landscape but shows the portrait image instead. I solved the problem by forcing a portrait view to appear by detecting for face up and down, but Apple's code solved this problem (as well as the similar movie problem I was also experiencing).
Many thanks for reporting the bug - I assumed it was just my bad coding...