access camera from uiwebview? - iphone

Is it possible to access iphone's camera from uiwebview? I know phonegap does it, but how to make it work without phonegap?
Thanks.

You can implement the UIWebView Delegate and intercept any attempted page load. By setting a custom url, you can pass a message to Objective C, that can launch the camera. To send data back to the web weiw you can initiate a new load (as I do in my example), or pass in some javascript using another method on UIWebView.
Here is a working example, I just wrote:
#import "WebViewCamAppDelegate.h"
#import <UIKit/UIKit.h>
#interface uiwebviewcameraAppDelegate : NSObject <UIApplicationDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIWebViewDelegate> {
UIWindow *window;
UIViewController *viewController;
UIWebView *webView;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
#implementation uiwebviewcameraAppDelegate
#synthesize window;
//This is the HTML we initially show in the WebView. Note the url "showcamera:" is one I
//invented with the intent to intercept it to show the camera.
static NSString *htmlString = #"<br>Show Camera";
//Pretty Basic stuff. We set the UIWebView Delegate so we can intercept the call and set up //a ViewController so we can animate the UIImagePicker
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
viewController = [[UIViewController alloc] init];
webView = [[UIWebView alloc] initWithFrame:window.bounds];
[webView loadHTMLString:htmlString baseURL:nil];
webView.delegate = self;
[viewController.view addSubview:webView];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
//Note: I check to make sure the camera is available. If it is not (iPod touch or Simulator) I show the photo library instead.
-(void) showCamera {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else {
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
imagePicker.delegate = self;
[viewController presentModalViewController:imagePicker animated:YES];
}
//Here we intercept any time the webview tries to load a document. When the user hits our "showcamera: url" we go to work.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([[[request URL] scheme] isEqualToString:#"showcamera"]) {
[self showCamera];
return NO;
}
return YES;
}
//After the imagepicker has done it's thing, we pass the data back to the webview to be displayed.
//If we wanted to be fancy here, we could have done this via Javascript so we could dynamically insert an image without reloading the page.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[viewController dismissModalViewControllerAnimated:YES];
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation (image, 0.5);
[webView loadData:imageData MIMEType:#"image/jpeg" textEncodingName:#"UTF-8" baseURL:nil];
}
- (void)dealloc {
[viewController release];
[webView release];
[window release];
[super dealloc];
}
#end

Related

Accessing the camera from the app itself

I am trying out a simple camera app for practice. Was following these examples: iOS 6 App
and iOS 4 App
My code looks like this:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
UIButton *button;
UIImageView *imageView;
}
#property (nonatomic, retain) IBOutlet UIImageView *imageView;
- (IBAction)useCamera;
- (IBAction)useCameraRoll;
#end
ViewController.m
#import "ViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize imageView;
- (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
// After saving iamge, dismiss camera
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
UIAlertView *alert;
// Unable to save the image
if (error)
alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to save image to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
else // All is well
alert = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"Image saved to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Save image
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (id)init
{
if (self = [super init])
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor grayColor];
// Button to activate camera
button = [[UIButton alloc] initWithFrame:CGRectMake(80, 55, 162, 53)];
[button setBackgroundImage:[UIImage imageNamed:#"Camera.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview:button];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)useCamera
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
- (IBAction)useCameraRoll
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
[self presentViewController:imagePicker animated:YES completion:nil];
}
}
#end
My problem I like to access the camera from the app itself. What happens is that when i click useCamera button, it opens up the camera and take the image. Is it possible it could do that from the app itself? Sorry if it is a stupid question. Do point me out if I am doing something wrong.
Yes, use the UIImagePickerController class.
When the camera button is clicked, present an instance of UIImagePickerController. Also, since some iOS devices like the original iPad or some older iPod touches don't have cameras, I wouldn't recommend using separate buttons/methods for taking a new picture vs using one from the saved photos. Use one button and set its source type based on the device's capabilities using the available methods in the class. It may require rethinking your app's design, but it's also more likely to pass Apple's UI inspection, as they may not approve an app that has a button exclusively for taking a picture but can run on a device without a camera.
Once the user has either taken a new photo or chosen a photo from either the camera roll, use the imagePickerController:didFinishPickingMediaWithInfo: method from the UIImagePickerControllerDelegate class to pass the user's choice to your code.
Instances of UIImagePickerController are designed to be presented modally on all iOS devices when using the camera. Remember, as the name suggests, they are controllers and NOT views, so they shouldn't be used as subviews of UIView. While it may be possible to get creative with how you present it, you'll almost certainly have some side-effects and you'll further increase the chance that Apple will reject it. It only SEEMS like it's getting out the app to take the photo, but because you're presenting the controller from your app, it's still very much a part of it. Apple doesn't allow direct access to the camera hardware, which is exactly why they've created this class.

TapDetectingWindow on WebView is not Working Properly

In my app I am using TapDetectingWindow to detect touches on a UIWebView (exactly as detailed on http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way).
I used it in one View Controller as suggested with a reference in the header file and the following in the implementation file like
- (id)init {
self = [super init];
if (self) {
tapDetectingWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0]; //mWindow, variable reference to TapDetectingWindow
tapDetectingWindow.viewToObserve = webView;
tapDetectingWindow.controllerThatObserves = self;
webView = [[UIWebView alloc] init];
[webView setFrame:CGRectMake(0, 0, 340, 1900)];
[webView setTag:1];
[webView addSubview:keyboardText];
[webView setUserInteractionEnabled:NO];
[webView setDelegate:self];
[webView setOpaque:0.0];
[webView loadHTMLString:htmlString baseURL:NULL];
[self.view addSubview:webView];
keyboardText = [[UITextField alloc] init];
keyboardText.autocorrectionType = UITextAutocorrectionTypeNo;
[keyboardText setDelegate:self];
[self.view addSubview:keyboardText];
}
return self;
}
but my app is crashing at
"tapDetectingWindow.viewToObserve = webView "
with a report * -[UIWindow setViewToObserve:]: unrecognized selector sent to instance 0x4a26b90
Can Any one help me out ...
The problem is not in the above code. Its due to new property introduction in iOS 5.0 with name window under UIApplicationDelegate protocol.
Change your window name in appdelegate file.
In .h file
#class WebViewController;
#class TapDetectingWindow;
#interface test_touchAppDelegate : NSObject <UIApplicationDelegate>
{
TapDetectingWindow *myWindow;
WebViewController *viewController;
}
#property (retain, nonatomic) TapDetectingWindow *myWindow;
#property (retain, nonatomic) WebViewController *viewController;
#end
In .m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.myWindow = [[TapDetectingWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[WebViewController alloc] init];
self.myWindow.rootViewController = self.viewController;
[self.myWindow makeKeyAndVisible];
return YES;
}
Hope this will help.
what Apurv told you is correct and work like a charm. I see you ask for alternate method to recognise gestures on a webview (I assume that it means click on UIWebView.). The answer is yes, you have to use " UIWebView delegate method ".
#pragma mark -
#pragma mark uiwebview delegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if(navigationType==UIWebViewNavigationTypeLinkClicked){
NSURL *URL = [request URL];
if(URL){
[[UIApplication sharedApplication] openURL:URL];
return NO;
}
}
return YES;
}
The code above, when you click on UIWebView, it will open the link of UIWebView that you clicked. Good luck.

UIImagePickerController having issues even after declaring from the Appdelegate

we are doing a photo application in which UIImagePickerController is used. For maintaining only one instance of the controller we have declared it in the appdelegate. But even after doing that memory leak is still there. Can any one please help us
Here's our code
In AppDelegate.h
UIImagePickerController *imagePicker;
#property (nonatomic, retain) UIImagePickerController *imagePicker;
In AppDelegate.m
#synthesize imagePicker;
and in applicationDidFinishLaunching event
imagePicker = [[[UIImagePickerController alloc] init] autorelease];
Need to call this UIImagePicker in CameraView
In CameraView.h
RedDawnMediaAppDelegate *appDel;
#property (nonatomic, retain) RedDawnMediaAppDelegate *appDel;
In CameraView.m
#synthesize appDel;
and in viewDidLoad
appDel=(RedDawnMediaAppDelegate*)[[UIApplication sharedApplication] delegate];
appDel.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
// Hide the camera controls:
appDel.imagePicker.showsCameraControls = NO;
appDel.imagePicker.navigationBarHidden = YES;
appDel.imagePicker.delegate = self;
// Make the view full screen:
appDel.imagePicker.wantsFullScreenLayout = YES;
appDel.imagePicker.cameraViewTransform = CGAffineTransformScale(appDel.imagePicker.cameraViewTransform, CAMERA_TRANSFORM_X, CAMERA_TRANSFORM_Y);
// Now incert our overlay view (it has to be here cuz it's a modal view):
appDel.imagePicker.cameraOverlayView = overlayView;
[self presentModalViewController:appDel.imagePicker animated:YES];
in didFinishPickingMediaWithInfo
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[appDelegate.imagePicker dismissModalViewControllerAnimated:YES];
uploadImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[uploadImage retain];
NSData *imageData = UIImageJPEGRepresentation(uploadImage, 0.5);
//[uploadImage release];
UIImage *image=[UIImage imageWithData:imageData];
self.view.frame = CGRectMake(0, 0, 320, 480);
self.wantsFullScreenLayout = YES;
objCameraImageView = [[CameraImageView alloc] initWithNibName:#"CameraImageView" bundle:[NSBundle mainBundle]];
[objCameraImageView setParentController:self];
objCameraImageView.cameraImage = image;
[image release];
uploadImage = nil;
[self.view addSubview:objCameraImageView.view];
[self release];
}
After taking a photo we are showing the preview in another view. so we are invoking the Cameraview for several times which is leading to Memory leak pls help.
First of all you dont need to worry about maintaining only one instance of imagepickercontroller. Getting an image from camera is much simpler than what you are doing.
See my post here:
How to take picture from Camera & saved in Photo Gallery by programmatically?
since Im releasing the picker when its done getting the image. There wont be memory leak!

Program received signal 0 for uiimagepickercontroller

I have an app where user can take picture from camera and image is displayed in imageview.
It works fine for the first time but the second time app is crashed leaving memory warning level=1
I google around and tried all possible ways but no use
Below is the code i used in my app
UIImagePickerController *imgpicker;
#property(nonatomic,retain) UIImagePickerController *imgpicker;
#synthesize imgpicker;
if(actionSheet.tag==1)
{
NSLog(#"button index:%i",buttonIndex);
if(buttonIndex == 0)
{ NSLog(#"button index for camera:%i",buttonIndex);
if(self.imgpicker==nil){
self.imgpicker=[[UIImagePickerController alloc]init];
self.imgpicker.delegate =self;
self.imgpicker.sourceType=UIImagePickerControllerSourceTypeCamera;
}
[self presentModalViewController:self.imgpicker animated:YES];
[imgpicker release];
return;
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSLog(#"didFinishPickingMediaWithInfo editing info:%#",info);
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
imageview = [[UIImageView alloc] initWithFrame:CGRectMake(65, 10, 75, 75)];
NSData *newjpg = UIImageJPEGRepresentation(image, 0.5);
[imageview setImage:[UIImage imageWithData:newjpg]];
[scrollView addSubview:imageview];
[self.view addSubview:scrollView];
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
Please help me
Try changing this:
self.imgpicker=[[UIImagePickerController alloc]init];
to this:
self.imgpicker=[[[UIImagePickerController alloc]init] autorelease];
and remove this line:
[imgpicker release];
If you're showing the image picker more than once, you're leaking memory from the image view that gets allocated every time the picker finishes.
You're also adding the image view to the scroll view and the scroll view to the view controller's view every time. You just need to do it once, and the update the image property on the image view.
Try this:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSLog(#"didFinishPickingMediaWithInfo editing info:%#",info);
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
if (imageview == nil) {
imageview = [[UIImageView alloc] initWithFrame:CGRectMake(65, 10, 75, 75)];
[scrollView addSubview:imageview];
[self.view addSubview:scrollView];
}
NSData *newjpg = UIImageJPEGRepresentation(image, 0.5);
[imageview setImage:[UIImage imageWithData:newjpg]];
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
Please create UIImagePickerController object in your AppDelegate class and initialize in your AppDidFinishloading method : didFinishLaunchingWithOptions. Realese it on appDelegate dealloc method.
You can access it in your needed view controller Page from appdelegate class.
Please do not create evertytime UIImagePickerController object when u needed and realese it.
This might help you.
Please use this code :
App Delegate
// .h
#import <UIKit/UIKit.h>
#interface MyProjectAppDelegate : NSObject <UIApplicationDelegate> {
UIImagePickerController *image_picker;
UIWindow *window;
UINavigationController *navigationController;
}
#property(nonatomic, retain) UIImagePickerController *image_picker;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
-(void)initializeImagePickerView;
#end
// .m
#import "MyProjectAppDelegate.h"
#import "RootViewController.h"
#implementation MyProjectAppDelegate
#synthesize window;
#synthesize navigationController,image_picker;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self initializeImagePickerView];
// Set the navigation controller as the window's root view controller and display.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
-(void)initializeImagePickerView
{
// Picker View
self.image_picker = [[UIImagePickerController alloc] init];
self.image_picker.allowsImageEditing = YES;
}
- (void)dealloc {
[image_picker release];
[navigationController release];
[window release];
[super dealloc];
}
#end
//RootView Controller
// .h
#import <UIKit/UIKit.h>
#import "MyProjectAppDelegate.h"
#interface RootViewController : UIViewController <UIImagePickerControllerDelegate,UINavigationControllerDelegate>{
MyProjectAppDelegate *appDelegate;
}
-(IBAction)btnPhotoPressed:(id)sender;
#end
// .m
#import "RootViewController.h"
#implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (MyProjectAppDelegate *)[[UIApplication sharedApplication] delegate];
}
-(IBAction)btnPhotoPressed:(id)sender
{
appDelegate.image_picker.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;
appDelegate.image_picker.delegate=self;
[self presentModalViewController:appDelegate.image_picker animated:YES];
}
#pragma mark UIImagePickerController delegate
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *imgCapturePhoto = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// You can use image here
[self dismissModalViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *) picker
{
[picker dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
}
This will definitely help u.

iPhone tabBar - How should I implement a Modal view so that each time a tab is selected it appears?

Could you tell me the best way to implement a Modal view so that it appears each time a certain tab is selected/pushed? Because the way I currently have my code results in all subsequent selections/pushes doing nothing.
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
UIImage *image;
IBOutlet UIImageView *imageView;
}
#end
#import "SecondViewController.h"
#implementation SecondViewController
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
imageView.image = image;
[self dismissModalViewControllerAnimated:YES];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
...
#end
You might check out
-(void)viewWillAppear {}