BMMedia framework for iOS

BMMedia framework for iOS

Released 4 years ago , Last update 4 years ago

A framework to handle loading, uploading, selection, storage and display of media within your iOS application. Bundled components include a full screen media viewer, a scrolling media thumbnail roll, a picker for items from the local media library, a custom camera and a whole lot of supporting classes and views.

Overview

Components to download, upload, store, view or select media items from different sources, part of the BMCommons library, which is the library upon which the BehindTheFrontDoor iPhone app is based. Download this free app to get an impression or view this demo which shows the most prominent features in a nutshell.

All code is fully documented with header documentation and a docset which you may install for context sensitive help within XCode.

The author, Werner Altewischer, has over 15 years experience as software developer and a track record of many successful apps since the launch of the app store in 2008 including the Greetz iPhone app, which won the award of best mobile web store of 2012 in The Netherlands.

This framework depends on the BMCore framework for iOS and the BMUICore framework for iOS.

The YouTube components shown in the video are available separately in the BMYouTube framework for iOS.

This framework is compatible with all iOS versions from 5.0 to 7.x.

Components

Full Screen Media Browser

  • Works in a similar fashion to the native Apple full screen media browser used in the "Photos" app
  • Support for loading media info from a local source or from a server
  • Support for both pictures, quicktime, mp4 and YouTube embedded videos
  • Supports native mode for YouTube video (play YouTube streams directly bypassing the UIWebView approach, which is the officially supported way, but looks worse)
  • Automatic "load more" functionality when user slides past the end of the loaded medias and the media are loaded from a remote source.
  • Full screen mode and thumbnail mode for quick-viewing all items
  • Auto rotation support
  • Support for adding and displaying captions
  • Support for customizing buttons in the toolbar to provide various functionalities (e.g. like, share, etc)
  • Support for deletion of items from the displayed selection of media with a trash can animation
  • Customizable styling (for some parts) and localization

Multi Selection Camera

  • Works in a similar fashion to the native Apple "Camera" app
  • Camera which allows taking more photos/videos in quick succession and viewing them or adding captions with the full screen media browser described above (compare with the normal UIImagePickerController which allows selection of only one item).
  • Configurable maximum allowed duration for video or number of photos/videos the user is allowed to take.
  • Auto-rotation support
  • Customizable localization.

Media Library Picker with multi-selection support

  • Works in a similar fashion to the selector used in the Apple native "Camera" app.
  • Allows selection of album from the asset library and viewing all media items in that album
  • Support for filtering out photos or videos or filtering on UTI (e.g. png, jpg, etc)
  • Optionally copies the media from the asset library for use in the app even if the original item is deleted.
  • Fast performance even with thousands of items in the library.
  • Threshold support for limiting the amount and type of items a user may select.
  • Customizable styling and localization.
  • Raw copy support to get access to the original full resolution images.
  • EXIF data returned for selected items if available.

Media roll component

  • A component to display media thumbnails in a horizontal scroll view embeddable in a UITableViewCell for example.
  • Support for snap to selection.
  • Optional repeat mode (infinitely scrolling media roll)
  • Remote loading support for loading media from a server
  • Full screen viewing of the media using the full screen media browser described above when user touches any of the thumbnails.
  • Customizable styling and localization

In addition to the components listed above there are a lot of supporting framework classes in this library that you can use that are part of the BMMedia module.

See also the overview of the BMCommons library here.

Pricing

14 day 14-day money-back guarantee

$199.99

Application License

  • Perpetual license

  • 1 application

  • Can distribute binary products only

  • Commercial use

  • 6 months support

$1,399.99

Distributor License

  • Perpetual license

  • Unlimited projects

  • Can distribute code and binary products

  • Commercial use

  • 6 months support

Documentation

The example project available in the free download (click 'View Demo') together with the official BMCommons documentation are probably the best documentation and shows how to use all APIs.

All code and samples are fully functional in the iOS simulator. For device usage you need a license key which requires a purchase.

The BMMediaSample target in the BMExamples project included in the download shows how to use most of the classes.

Take a look in particular at the ViewController and AppDelegate classes. Also look at the CustomStyleSheet class to see how you can customize the styles of the various controls.

The strings resources bundled in the example show how you can alter strings for a particular locale. Beware that you need to use separate strings tables as shown (BMUICore.strings, BMMedia.strings, etc) because the modules look in a string table with the same name as the name of the module.

Localization

The BMLocalization class redefines the NSLocalizedString macros and also adds support to decouple the app locale from the system locale. By sub classing BMViewController or BMTableViewController and overriding the 'localize' method it is possible to respond to in-app locale changes. It's also possible to subscribe manually to the shared instance of the BMLocalization class as a listener to receive notifications about locale changes.

Managing Services

The AppDelegate shows how to centralize support for a loading indicator and cancellation of running services or even send them to the background for long running tasks (e.g. upload of media). You are strongly encouraged to take a look at the BMService protocol and BMServiceManager class both of which are used heavily internally. You are free to write your own BMService implementations to hook into this. Typically you would want to extend from the BMAbstractService class or one of its concrete sub classes.

Media Controls

The ViewController class shows how to incorporate the different controls. It shows how to instantiate the three different types of BMMediaPickerControllers (Camera, Media library and also YouTube, which is available separately) and how to show the full screen media browser. It also shows how to present a horizontal media roll and how to reload it. In addition it shows how to save the selected data to disk and to load them again.

The example uses the default implementations of BMMediaContainer which make use of the NSCoding protocol for saving. However, if you would like to create your own implementations this is possible (e.g. when you want to use CoreData). The source code of the default implementations is attached (see the 'Sources' directory) so you may take a look at that for a clue on how to create a custom implementation. You can also choose just to use different storage strategy for the media data itself. Create a custom implementation of BMMediaStorage if you want to do that (again take a look at the Sources directory to get an example in BMURLCacheMediaStorage).

Setup / installation

To install:

  • Unzip the downloaded zip-file which contains the BMCommons frameworks, documentation and example code
  • Copy the docset included in the Documentation directory to your XCode docset directory as specified in the README.md file included in the download.
  • Add the BMCore.framework, BMUICore.framework and BMMedia.framework from the Frameworks directory to your project's target.
  • A license key is required for productional use on an iOS device. Register the license key in your AppDelegate's init method as follows:

    [[BMCore instance] registerLicenseKey:@"TheLicenseKey"]; [[BMUICore instance] registerLicenseKey:@"TheLicenseKey"]; [[BMMedia instance] registerLicenseKey:@"TheLicenseKey"];

This module depends on the BMCore framework for iOS and the BMUICore framework for iOS and the dynamic framework/libraries mentioned there. Additionally this module requires linking with the following frameworks/libraries:

  • CoreLocation.framework
  • MediaPlayer.framework
  • AVFoundation.framework
  • AssetsLibrary.framework

Example usage

To present a media picker (different source types)

- (void)pickImageWithSourceType:(ImagePickerSourceType)sourceType andAuthentication:(id)authentication {
    if (!_mediaPickerController) {
        if (sourceType == ImagePickerSourceTypeCamera) {
            _mediaPickerController = [[BMCameraController alloc] init];
            ((BMCameraController *)_mediaPickerController).saveToCameraRoll = YES;
        } else if (sourceType == ImagePickerSourceTypeMediaLibrary) {
            _mediaPickerController = [[BMMediaLibraryPickerController alloc] init];
        } else if (sourceType == ImagePickerSourceTypeYouTube) {
            BMYouTubePickerController *youTubePickerController = [[BMYouTubePickerController alloc] init];
            youTubePickerController.authentication = authentication;
            youTubePickerController.useNativeMode = _youTubeModeSwitch.on;
            _mediaPickerController = youTubePickerController;
        }

        //Sets a custom stylesheet for the view controller
        _mediaPickerController.styleSheet = [[[CustomStyleSheet alloc] init] autorelease];

        //Configure the picker with max selectable items, max duration and other parameters
        _mediaPickerController.maxSelectableMedia = MAX_MEDIA_COUNT - [_mediaSource numberOfMediaPhotos];
        _mediaPickerController.maxSelectablePictures = MAX_PICTURE_COUNT - [_mediaSource numberOfPicturePhotos];
        _mediaPickerController.maxSelectableVideos = MAX_VIDEO_COUNT - [_mediaSource numberOfVideoPhotos];
        _mediaPickerController.maxDuration = MAX_VIDEO_DURATION;
        _mediaPickerController.allowMixedMediaTypes = YES;
        _mediaPickerController.delegate = self;

        //Present the picker
        if (![_mediaPickerController presentFromViewController:self]) {
            BM_AUTORELEASE_SAFELY(_mediaPickerController);
        }
    }
}

Typical delegate implementation

/**
 @brief Sent when the media picker is dismissed. The array of media contains the media items that were selected.
 */
- (void)mediaPickerControllerWasDismissed:(BMMediaPickerController *)controller withMedia:(NSArray *)media {
    if (controller == _mediaPickerController) {
        //Add the media items added to the media source
        [_mediaSource addMedia:media];

        //Save to disk
        [self save];

        //And reload the media roll to reflect the added media
        [self reloadMediaRoll];

        //Release the media picker controller after use
        BM_RELEASE_SAFELY(_mediaPickerController);
    }
}

/**
 Sent when the picker is cancelled.
 */
- (void)mediaPickerControllerWasCancelled:(BMMediaPickerController *)controller {
    if (controller == _mediaPickerController) {
        //Release the media picker controller after use
        BM_RELEASE_SAFELY(_mediaPickerController);
    }
}

/**
 @brief Should return a new autoreleased instance of BMVideoContainer for use to store the information when a video is selected/recorded.
 */
- (id <BMVideoContainer>)videoContainerForMediaPickerController:(BMMediaPickerController *)controller {
    //BMVideo is the default implementation of the protocol BMVideoContainer which stores items in the BMURLCache as pinned cache entries.
    //Pinned means they will never be automatically removed.
    return [[[BMVideo alloc] init] autorelease];
}

/**
 @brief Should return a new autoreleased instance of BMPictureContainer for use to store the information when a picture is selected/taken.
 */
- (id <BMPictureContainer>)pictureContainerForMediaPickerController:(BMMediaPickerController *)controller {
    //BMPicture is the default implementation of the protocol BMPictureContainer which stores items in the BMURLCache as pinned cache entries.
    //Pinned means they will never be automatically removed.
    return [[[BMPicture alloc] init] autorelease];
}

/**
 @brief Called when the max number of selectable media was reached. Use this to show an appropriate alert for example.
 */
- (void)mediaPickerControllerReachedMaxSelectableMedia:(BMMediaPickerController *)controller {
    //BMDialogHelper is a utility class for showing dialogs
    [BMDialogHelper alertWithTitle:@"Sorry" message:@"You reached the max number of selectable media." delegate:nil];
}

/**
 @brief Called when the max duration for a video was reached. Use this to show an appropriate alert for example.
 */
- (void)mediaPickerControllerReachedMaxDuration:(BMMediaPickerController *)controller {
    [BMDialogHelper alertWithTitle:@"Sorry" message:@"This video exceeds the maximum allowed duration" delegate:nil];
}

- (BOOL)mediaPickerController:(BMMediaPickerController *)controller shouldAllowSelectionOfMedia:(id<BMMediaContainer>)mediaItem {
    BOOL exists = NO;

    for (id <BMMediaContainer> mc in _mediaSource.media) {
        if ([mc.entryId isEqual:mediaItem.entryId]) {
            exists = YES;
            break;
        }
    }

    if (exists) {
        //Show a dialog to the user that the chosen item is already in his list of selected items
        [BMDialogHelper alertWithTitle:@"Sorry" message:@"You already selected this item, please select another one" delegate:nil];
    }

    return !exists;
}

To present the full-screen media browser:

- (void)showFullScreenBrowserWithPhoto:(id <BMTTPhoto>)selectedPhoto fromViewController:(UIViewController *)vc {
    if (!_mediaBrowserController) {
        _mediaBrowserController = [[BMFullScreenMediaBrowserViewController alloc] initWithPhoto:selectedPhoto showEditingButtons:YES];
        _mediaBrowserController.styleSheet = [[CustomStyleSheet new] autorelease];
        _mediaBrowserController.delegate = self;
        _mediaBrowserController.nativeYouTubeModeEnabled = _youTubeModeSwitch.on;

        //Present the media browser within a navigation controller.
        //We use BMNavigationController here because it has support for different animations, such as the curl up and down which is used to present the thumbnail overview.
        UIViewController *navController = [[BMNavigationController alloc] initWithRootViewController:_mediaBrowserController];

        [vc presentModalViewController:navController animated:YES];

        [navController release];
    }
}

For more code examples see the example project included in the download or post a question.

License

Three licenses are offered for this module:

  • Application License: valid for a single application (binary code only);
  • Developer License: valid for either 5 applications with generic bundle identifiers or for all applications within your company, with application bundle identifiers matching to com.yourcompany.* (binary code only);
  • Distributor License: valid for unlimited applications, including the source code. Gives you right to distribute the source code or binary as part of a bigger project, but prohibits reselling the library itself.

NOTE: Only the distributor package contains the source code for this module. Other packages include the binary library only.

The demo download includes all modules of the BMCommons framework including example code with unlimited functionality in the iOS simulator. Running on an actual device requires a valid license key to be registered as follows:

[[BMMedia instance] registerLicenseKey:@"TheLicenseKey"];

License keys may be managed via https://license.behindmedia.com. You may also request a trial there.

3 licenses, starting from From » $199.99 View Licenses

Get A Quote

What do you need?
  • Custom development
  • Integration
  • Customization / Reskinning
  • Consultation
When do you need it?
  • Soon
  • Next week
  • Next month
  • Anytime

Thanks for getting in touch!

Your quote details have been received and we'll get back to you soon.


Or enter your name and Email
No comments have been posted yet.