简体   繁体   中英

Access active Mediaplayer from DetailViewController in App Deligate UISplitViewController (MobileVLCKit)

Im currently developing a videostreaming iOS App with the MobileVLCKit framework. To navigate through the different transmitters I use the UISplitViewController . The App works fine until I lock the screen of the iPad 3. I Debugged the code and know that the player is still running in the background. I have to access the media player property (_mediaplayer) to stop the player if it gets resign or enters background in app deligate.

I have searched in the www and on stackoverflow, but it seems to be a little part that i might not see or misunderstand. I would be very pleased if someone could take a minute and help me spot the problem.

btw. Yeah my first post on SO, after nearly two years of using it :D

Question: How can I access the property in the appDeligate.m?

AppDeligate.h

#import <UIKit/UIKit.h>

@class DetailViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
    UISplitViewController *splitViewController;
}

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) DetailViewController *viewController;

@end

AppDeligate.m

#import "AppDelegate.h"
#import "DetailViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    splitViewController.delegate = (id)navigationController.topViewController;

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.

    DetailViewController *thePlayer = [[splitViewController viewControllers] objectAtIndex:1];

    if(thePlayer._mediaplayer.isPlaying == true) {
        NSLog(@"Player is playing");
    }

    NSLog(@"Background");
}

DetailViewController.h

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController <UISplitViewControllerDelegate>

@property (strong, nonatomic) VLCMediaPlayer* _mediaplayer;
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UIView *movieView;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;

@end

DetailViewController.m

#import "DetailViewController.h"

@interface DetailViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
@end

@implementation DetailViewController

@synthesize _mediaplayer;


#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
    NSLog(@"setDetailItem");
    if (_detailItem != newDetailItem) {
        _detailItem = newDetailItem;

        // Update the view.
        [self configureView];
    }
}

- (void)mediaPlayerStateChanged:(NSNotification *)aNotification
{
    VLCMediaPlayerState currentState = _mediaplayer.state;

    /* Playback opening */
    if (currentState == VLCMediaPlayerStateOpening) {
        [self.indicator startAnimating];
        NSLog(@"Openning");
    }

    /* or if playback ended */
    if (currentState == VLCMediaPlayerStateEnded || currentState == VLCMediaPlayerStateStopped) {
        NSLog(@"Stopped");
        [self.indicator stopAnimating];
    }

    /* Playback buffering */
    if (currentState == VLCMediaPlayerStateBuffering) {
        NSLog(@"buffering");
        [self.indicator startAnimating];
    }

    /* Playback buffering */
    if (currentState == VLCMediaPlayerStatePlaying) {
        NSLog(@"Playing");
        [self.indicator stopAnimating];
    }
}

- (void)configureView
{
    NSLog(@"configureView");
    // Update the user interface for the detail item.

    if (self.detailItem) {

        self.imageView.image = nil;

        if(self._mediaplayer.isPlaying) {
            // Stop active media
            [self._mediaplayer stop];
        }

        // Set new url
        self._mediaplayer.media = [VLCMedia mediaWithURL:[NSURL URLWithString:_detailItem]];

        // Play new media
        [self._mediaplayer play];

        // Set radio image
        if ([_detailItem rangeOfString:@"239.192.1"].location != NSNotFound) {
            [self.imageView setImage:[[UIImage imageNamed:@"music.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
            self.imageView.contentMode = UIViewContentModeCenter;
        }


    }
}

- (void)viewDidDisappear
{
    NSLog(@"viewDidDisappear");
    if (self._mediaplayer) {
        @try {
            [self._mediaplayer removeObserver:self forKeyPath:@"time"];
            [self._mediaplayer removeObserver:self forKeyPath:@"remainingTime"];
        }
        @catch (NSException *exception) {
            NSLog(@"we weren't an observer yet");
        }
        if (self._mediaplayer.media)
            [self._mediaplayer stop];

        if (self._mediaplayer)
            self._mediaplayer = nil;
    }
}

- (void)viewDidLoad
{
    NSLog(@"viewDidLoad");
    [super viewDidLoad];

    // Hide navbar
    [[self navigationController] setNavigationBarHidden:YES animated:YES];

    // Background logo
    [self.imageView setImage:[[UIImage imageNamed:@"background.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
    self.imageView.contentMode = UIViewContentModeCenter;

    // Init media player
    [self initMediaplayer];
}

- (void)initMediaplayer
{
    self._mediaplayer = [[VLCMediaPlayer alloc] init];
    self._mediaplayer.delegate = self;
    self._mediaplayer.drawable = self.movieView;
    NSLog(@"Init VLC Player");
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Split view

- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:
(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
    return YES;
}


@end

Make splitViewController an instance variable in @interface and than change:

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.

    DetailViewController *thePlayer = [[splitViewController viewControllers] objectAtIndex:1];
    [thePlayer._mediaplayer stop];

    NSLog(@"Resign");
}

This is the final code which worked for me. Feel free to use!

AppDelegate.h

#import <UIKit/UIKit.h>

@class DetailViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) DetailViewController *viewController;

@end

AppDelegate.m

#import "AppDelegate.h"
#import "DetailViewController.h"

@interface AppDelegate () {
    UISplitViewController *splitViewController;
    UINavigationController *navigationController;
    VLCMedia *currentPlayback;
}

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    splitViewController = (UISplitViewController *)self.window.rootViewController;
    navigationController = [splitViewController.viewControllers lastObject];
    splitViewController.delegate = (id)navigationController.topViewController;

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSLog(@"WillResignActive");
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"DidEnterBackground");

    DetailViewController *dvc = (DetailViewController *)navigationController.topViewController;
    if (dvc._mediaplayer.isPlaying) {
        [dvc._mediaplayer stop];
        NSLog(@"Mediaplyer stopped");
        currentPlayback = dvc._mediaplayer.media;
        NSLog(@"Saved current playback");

        while (dvc._mediaplayer.isPlaying) {
            [NSThread sleepForTimeInterval:0.1];
        }
    }

    if (dvc._mediaplayer != nil) {
        dvc._mediaplayer = nil;
        NSLog(@"Set player to nil");
    }
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"WillenterForeground");
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"DidBecomeActive");
    DetailViewController *dvc = (DetailViewController *)navigationController.topViewController;
    if (dvc._mediaplayer == nil) {
        dvc._mediaplayer = [[VLCMediaPlayer alloc] init];
        dvc._mediaplayer.delegate = self;
        dvc._mediaplayer.drawable = dvc.movieView;
        NSLog(@"init mediaplayer");
    }

    if (currentPlayback != nil || dvc._mediaplayer.media == nil) {
        dvc._mediaplayer.media = currentPlayback;
        NSLog(@"set current playback media");
    }

    if (dvc._mediaplayer.media != nil || dvc._mediaplayer.isPlaying == false) {
        [dvc._mediaplayer play];
        NSLog(@"play");
    }
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

DetailViewController.h

#import <UIKit/UIKit.h>
#import <MobileVLCKit/MobileVLCKit.h>

@interface DetailViewController : UIViewController <UISplitViewControllerDelegate>

@property (strong, nonatomic) IBOutlet UITapGestureRecognizer *tapGestureRecognizer;
@property (strong, nonatomic) VLCMediaPlayer* _mediaplayer;
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UIView *movieView;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;

@end

DetailViewController.m

#import "DetailViewController.h"

@interface DetailViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
@property (strong, nonatomic) UIBarButtonItem *barButton;
@end

@implementation DetailViewController

@synthesize _mediaplayer;

- (IBAction)handleTap:(UITapGestureRecognizer *)sender {
    [_barButton.target performSelector: _barButton.action withObject: _barButton];
}

#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
    NSLog(@"setDetailItem");
    if (_detailItem != newDetailItem) {
        _detailItem = newDetailItem;

        // Update the view.
        [self configureView];
    }
}

- (void)mediaPlayerStateChanged:(NSNotification *)aNotification
{
    VLCMediaPlayerState currentState = _mediaplayer.state;

    /* Playback opening */
    if (currentState == VLCMediaPlayerStateOpening) {
        [self.indicator startAnimating];
        NSLog(@"Openning");
    }

    /* or if playback ended */
    if (currentState == VLCMediaPlayerStateEnded || currentState == VLCMediaPlayerStateStopped) {
        NSLog(@"Stopped");
        [self.indicator stopAnimating];
    }

    /* Playback buffering */
    if (currentState == VLCMediaPlayerStateBuffering) {
        NSLog(@"buffering");
        [self.indicator startAnimating];
    }

    /* Playback buffering */
    if (currentState == VLCMediaPlayerStatePlaying) {
        NSLog(@"Playing");
        [self.indicator stopAnimating];
    }
}

- (void)configureView
{
    NSLog(@"configureView");
    // Update the user interface for the detail item.

    if (self.detailItem) {

        self.imageView.image = nil;

        if(_mediaplayer.isPlaying) {
            // Stop active media
            [_mediaplayer stop];
        }

        // Set new url
        _mediaplayer.media = [VLCMedia mediaWithURL:[NSURL URLWithString:_detailItem]];

        // Play new media
        [_mediaplayer play];

        // Set radio image
        if ([_detailItem rangeOfString:@"239.192.1"].location != NSNotFound) {
            [self.imageView setImage:[[UIImage imageNamed:@"music.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
            self.imageView.contentMode = UIViewContentModeCenter;
        }
    }
}

- (void)viewDidLoad
{
    NSLog(@"viewDidLoad");
    [super viewDidLoad];

    // Hide navbar
    [[self navigationController] setNavigationBarHidden:YES animated:YES];

    // Show navbar
    [_barButton.target performSelector: _barButton.action withObject: _barButton afterDelay:1];

    // Background logo
    [self.imageView setImage:[[UIImage imageNamed:@"background.png"] imageWithRenderingMode: UIImageRenderingModeAlwaysOriginal]];
    self.imageView.contentMode = UIViewContentModeCenter;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Split view

- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:
(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
    return YES;
}

- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
    _barButton = barButtonItem;
}
@end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM