ios Archives — Now Playing Apps Let's build it together Sun, 22 Mar 2020 02:32:46 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.1 151952093 Better iOS ratings and reviews using SKStoreReviewController https://nowplayingapps.com/ios-rating-and-review-prompt-using-skstorereviewcontroller/ Sun, 22 Mar 2020 02:04:28 +0000 https://nowplayingapps.com/?p=333 Learn how to implement iOS Rating and Review prompt along with some best practices to maximize positive feedback from your audience

The post Better iOS ratings and reviews using SKStoreReviewController appeared first on Now Playing Apps.

]]>
The iOS app store has millions of apps for each category and as a developer, it is hard to stand out even if you provide great functionalities. Positive ratings and reviews are the major factors that impact the discoverability of your app in the app store. Apple provides a great way to collect positive (or negative) feedback directly from your users right inside the app using iOS rating and review prompt. Let’s see how.

Apple has provided an easy way to request ratings and reviews from your audience. This StoreKit API called SKStoreReviewController has a static function called requestReview() that will display an iOS rating and review prompt to collect the feedback. Here’s how we trigger it:

import StoreKit

@available(iOS 10.3, *)
class RatingManager {

    static func displayRatingPrompt() {
        SKStoreReviewController.requestReview()
    }
    
}

This API works only on iOS 10.3 and above. For iOS versions prior to this, please see the manually requesting a review section. Also, be sure to check out the best practices for displaying iOS rating and review prompt.

Review prompt will still display even in development mode or builds that are distributed through TestFlight for testing purposes, but will not affect the App Store rating or reviews.

Using UserDefaults to control the frequency of iOS rating and review prompt

You also need to be aware that this modal will only get presented to a maximum of 3 times in a year (or 365 days period). So deciding when and where the modal should appear should be chosen carefully. Here are some utility functions to be added to your RatingManager class to help us with it:

private static let promptDisplayLimitPerVersion = 3
private static let promptCounterKey = "RatingReviewPromptDisplayCounter"
private static let promptLastDisplayedVersionKey = "RatingReviewPromptLastDisplayedKey"

/// returns current app version in string format
private static func currentAppVersion() -> String {
    let currentVersion = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
    return currentVersion ?? ""
}

/// every time rating prompt is shown to the user, it will be persisted in user defaults
/// this function returns the app version in which rating prompt is last shown to the user.
private static func lastRatingPromptDisplayedAppVersion() -> String {
    let lastDisplayedVersion = UserDefaults.standard.string(forKey: promptLastDisplayedVersionKey)
    return lastDisplayedVersion ?? ""
}

/// set current version of the app as the last version
/// on which rating prompt was displayed
private static func setCurrentAsPromptDisplayedVersion() {
    UserDefaults.standard.set(currentAppVersion(), forKey: promptLastDisplayedVersionKey)
}

/// returns an integer that represents how many times rating prompt
/// is displayed to the user in the current version of the app
private static func displayCount() -> Int {
    return UserDefaults.standard.integer(forKey: promptCounterKey)
}

/// when a rating is prompted to the user, increment the counter
private static func incrementDisplayCount() {
    var count = displayCount()
    count += 1
    UserDefaults.standard.set(count, forKey: promptCounterKey)
}

/// reset the app display counter
private static func resetDisplayCount() {
    UserDefaults.standard.set(0, forKey: promptCounterKey)
}

and now changing the rating prompt initialization like this:

import StoreKit

@available(iOS 10.3, *)
class RatingManager {
    
    static func requestReviewIfNeeded() {
        let appVersionDidChange = currentAppVersion() == lastRatingPromptDisplayedAppVersion()
        let displayCountDidReachLimit = displayCount() >= promptDisplayLimitPerVersion
        
        if appVersionDidChange {
            // the app version has changed since the previous prompt is shown to the user
            // so it is safe to display the prompt `promptDisplayLimitPerVersion` times.
            resetDisplayCount()
        }
        
        if !displayCountDidReachLimit {
            displayRatingPrompt()
            incrementDisplayCount()
            setCurrentAsPromptDisplayedVersion()
        }
    }
    
    private static func displayRatingPrompt() {
        SKStoreReviewController.requestReview()
    }
    
    /// insert utility functions here...
}

Now, requestReviewIfNeeded is the only front-facing function for RatingManager and when you request for a rating prompt, it will take all the necessary checks into consideration.

Manually requesting a review

We have certain checks inside our RatingManager class to decide whether or not to display the rating prompt or not. However, you can manually take the user to the App Store review page when the user wishes to do so (say, if you have a “review this app” button in the settings). All you need to do at this time is to open your App Store URL.

/// Open App Store URL to request a manual review from the user
static func manualRequestAppReview(appId: String) {
    let appStoreURL = "https://itunes.apple.com/app/\(appId)?action=write-review"
    guard let reviewURL = URL(string: appStoreURL) else {
        return
    }
    
    UIApplication.shared.open(reviewURL, options: [:], completionHandler: nil)
}

Some best practices for iOS rating and review prompt

  1. Avoid showing rating and review modal as soon the user opens the app. This should be the case even if it is not the first time the user is opening your app.
  2. Let the user use the app for a couple of days (or maybe weeks), and only request a review after they get a chance to play with main functionalities.
  3. Ask for a review at the right time. Probably not a good idea to do so after they lost a game level or dismissed an ad.
  4. Give enough time interval between rating requests. A frequent request might work against you.

Adding a review prompt is also one of the top five features your app should have. To read more about all the essentials features of an app to succeed, please check out my blog post here.

Conclusion

As you just saw, it is very easy to get feedback from your users without having to do much work by using APIs provided by iOS. Implementing this feature following the best practices can help you collect positive feedback, which will translate to better visibility in the App Store.

The post Better iOS ratings and reviews using SKStoreReviewController appeared first on Now Playing Apps.

]]>
333
Handling audio interruptions in your iOS app https://nowplayingapps.com/handling-audio-interruptions-in-your-audio-app/ Mon, 10 Feb 2020 02:46:57 +0000 https://nowplayingapps.com/?p=304 Handling audio interruptions is key to improving user experience of your app. This article describes how to handle such interruptions gracefully

The post Handling audio interruptions in your iOS app appeared first on Now Playing Apps.

]]>
Interruptions are common in any type of software system. It is even more important in the case of mobile apps, starting with network interruptions to other common ones such as receiving calls or alarm notifications (also called audio interruption). Handling these audio interruptions will enhance the user experience gracefully.

Common types of audio interruptions

  1. Receiving incoming or making outgoing calls
  2. Alarm or timer notifications
  3. Other app takes over the iOS audio session (for example user opens a podcast app and starts playing it while your music app was playing)

How does the operating system handles interruption?

  1. Operating System deactivates your apps audio session
  2. Sends a notification through NSNotificationCenter saying an interruption has occurred. This will allow your app to gracefully respond to the interruption, for example, by pausing/stopping your playback and updating the UI states – such as display paused icon
  3. Once the interruption has ended, the operating system sends another notification confirming the interruption has ended. This will allow your app can respond to it (by resuming the playback and updating the UI state – display playing icon)

So basically, in order to handle these interruptions, all you need to do is listen to interruption notifications, and respond to it accordingly. Let’s see how.

Listening to audio interruption notifications

This can be done by adding an observer for AVAudioSession.interruptionNotification event.

private func addInterruptionsObserver() {
    NotificationCenter.default.addObserver(self,
                   selector: #selector(handleInterruption),
                   name: AVAudioSession.interruptionNotification,
                   object: nil)
}

Make sure that your app’s AVAudioSession is set before this observer is added.

How to gracefully handle audio interruptions

Once the observer is set, handleAudioInterruption will now receive notifications when an interruption begins and ends.

@objc private func handleInterruption(notification: Notification) {
    guard let userInfo = notification.userInfo,
        let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
        let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
    }
    
    switch type {
    case .began:
        // pause audio
        // update player UI state to paused
        
    case .ended:
        //  resume audio playback
        // update player UI state to playing
        // set audio session
        
    default: break
    }
}

If the AVAudioSession.InterruptionType == .ended, there may also be extra info inside the userInfo dictionary called AVAudioSession.InterruptionOptions which has a static property called shouldResume. This tells you whether your app is ready to be resumed.

guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else {
    return
}

let options = AVAudioSessionInterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
    // Interruption Ended - playback should resume
}

And that’s it. Your app is now configured to handle audio interruptions gracefully.

Conclusion

Handling audio interruption is very essential to good user experience, and by listening to the events sent by iOS, it is an easy win for any media application.

The post Handling audio interruptions in your iOS app appeared first on Now Playing Apps.

]]>
304
How to promote your iOS app with Smart App Banner https://nowplayingapps.com/configure-smart-app-banner/ Sat, 17 Aug 2019 17:56:51 +0000 https://nowplayingapps.com/?p=221 Smart App Banner is an easy way to drive more engagement to your iOS app. Learn why it is important and how easy it is configure it on your website.

The post How to promote your iOS app with Smart App Banner appeared first on Now Playing Apps.

]]>
Have you ever noticed that when you visit some most popular websites (like PayPal or Trello), the Safari browser displays a beautifully laid out banner ad which contains a description of their iOS app and a call to action to download (if not installed) or view (if already installed) it? This is a feature is called Smart App Banner and is introduced in iOS 6 intended to promote your iOS app to users visiting your website and thereby driving more users to the mobile app. 

Advantages of Smart App Banner over a custom ad banner implementation

Of course, one may think that custom implementation of a similar banner would be an easy implementation on the server (web) side, but Smart App Banner offers many features that are very hard or may not even be possible to achieve.

  • Common look and feel across other products and hence won’t be mistaken as clickbait or spam advertisement
  • Clean presentation at the top without obstructing the main web content
  • Easy to get rid of, and once closed, it won’t re-appear on subsequent visits
  • Intelligently identify whether the app is installed, and thereby redirecting directly to the app instead of app store
  • If the app does not support the user’s device (due to minimum SDK version or location), the smart app banner won’t be displayed
  • Displays progress bar inside the banner to convey installation progress of the app from the app store

Alright, enough said about the benefits. Now, let us look at how to implement these smart app banners for your website and thereby giving a boost to your iOS app.

Implementing Smart App Banner

To get a Smart App Banner setup, you only need two things 

  1. Appstore id of your app
  2. Access to your web app backend

Step 1: Get Appstore id of your app

The easiest way to get the appId is to inspect the Appstore URL. Usually, appId will be appended towards the end of the URL. For example, in Canadian Appstore, Paypal URL is https://apps.apple.com/ca/app/paypal/id283646709 where “283646709” is the app id.

Getting App Id from App Store URL
App Id from App Store URL

However, this way of finding the appId from the App Store URL is not officially documented and may change any time in the future. Alternatively, you can locate the appId inside your iTunesConnect account under the App Information tab.

Getting App Id from iTunesConnect
App Id from iTunesConnect

Step 2: Add meta tag to your website.

Once you have your appId, we need to tell Safari that an in-market app is linked to this website. This is done by adding a meta tag inside the head tag of your website as shown below.

<meta name="apple-itunes-app" content="app-id=app-id-from-step1"/>

That’s it! When a new user comes to your site, Safari will identify your app in the app store and show the Smart App Banner.

What’s next?

There is also a provision to provide extra information in the meta tag in order to make seamless navigation to the iOS app. You can read more in the Intelligent deeplink from Smart App Banner article.

Conclusion

Smart App Banner is truly a smart way to increase traffic to your iOS app, and it takes care of many use cases on your behalf that you’ll have to manually implement on your website otherwise.

The post How to promote your iOS app with Smart App Banner appeared first on Now Playing Apps.

]]>
221
How to choose the right chromecast receiver for your iOS app https://nowplayingapps.com/chromecast-receiver-types/ Thu, 07 Mar 2019 02:13:26 +0000 https://nowplayingapps.com/?p=147 Discuss different chromecast receiver types available and helps you decide which one is right for your app.

The post How to choose the right chromecast receiver for your iOS app appeared first on Now Playing Apps.

]]>
Chromecast is one of the vital components of any stream (audio/video) app. It gives your customers ability to enjoy your content on the big screen in their living room. Although, Google makes it really easy to add google-cast sdk into your app, it is important on how it is rendered on the receiver side. This post reviews the different options available to you on the receiver side of chromecast.

Get started

Get started by registering your application at console at cast.google.com/publish. Registration is not required if you plan to use Default Media Receiver. Once the app is published, we’re ready to start testing of the app.

There are mainly three types of chromecast receiver apps.

  • Default Media Receiver
  • Styled Media Receiver
  • Custom Receiver

The complexity of setting receiver app increases as you go down the list. For example, the easiest one is Default Media Receiver.

Default Media Receiver

Google has done all the work here, and all you need to do in your client side app is to tell that you intend to use the default receiver. In iOS, this can be achieved by using kGCKDefaultMediaReceiverApplicationID as the application id.

The styling and branding of the Default Media Receiver comes out of the box and cannot be changed. This is the most inexpensive and fast way to bring your content to chromecast. But as you get more serious about the branding of your app, you might want to go with more flexible receivers such as Styled Media Receiver or Custom Chromecast Receiver.

Styled Media Receiver

Styled media receivers are a bit more flexible in terms of styling but not so much. At the time of registering the app, there is an option to provide a stylesheet. This is used to control components such as background image, splash screen, logo and progress bar color. An example stylesheet and more details can be found at at the documentation website. The app registration console will load the stylesheet dynamically so that we can see how the app would look like, based on the style classes specified in the css file.

Styled media receivers are suitable for most of the apps because the Chromecast itself manages the receiver side code. Also, it gives us a flexibility to modify the styling based on the app’s branding. However, if you are looking for full control over the appearance and behaviour of the receiver app, then writing a custom receiver app will be the best option for you.

Custom Chromecast Receiver

A custom receiver is basically an html/css/javascript application, which you develop, that runs on a Chromecast device. Chromecast is basically a glorified chrome browser, and hence it can render any html content just like the browser. The app is designed using html and css, and javascript is used to monitor the player changes, and you (as the developer of Chromecast app) can respond to the player changes (such as launching, idle, loading, buffering, paused and playing).

Another good reason to choose a custom implementation is to change the metadata shown on Chromecast needs to change without having to use the sender application. For example, if you are casting a live stream radio, and every five minutes the song changes, and you want to update it on Chromecast. Using a Default Media Receiver or Styled Media Receiver cannot do this, however, since Custom Receiver is a javascript application, we can write code to achieve this.

The playback is usually done using html media tag (<audio></audio> or <video></video>). And using the javascript code, you can access this element and control the playback after reading the metadata sent from sender (iOS/Android/Web) application.

General scenarios

Here are some very common scenarios and solutions to decide which flavour of receiver app to choose.

Choose Default Media Receiver if,

  • You have a video/audio streaming app and you don’t care about how the chromecast app looks like.
  • The app does not require special unlocking to playback (Authentication/DRM or decryption).
  • Don’t want to host and manage custom html/css/javascript code.

Choose Styled Media Receiver if,

  • You want to theme your chromecast to match the branding, but don’t want to spend time hiring a developer and building out a custom app
  • The app does not require special unlocking to playback (Authentication/DRM or decryption)
  • Don’t want to host and manage custom html/javascript code. However, the custom CSS file needs to be hosted through https

Choose Custom Chromecast Receiver if,

  • You care about how the chromecast looks like and need full control of its behavior
  • Playback require unlocking (Authentication/DRM or decryption)
  • It is okay to host and manage custom receiver code (html/css/javascript)
  • The receiver application needs to change metadata shown on screen without the involvement of the sender application

Conclusion

Building and debugging a custom receiver is a bit more involved work than the other two options. So you need to make the decision whether to spend all the time developing it, or to just use a styled receiver and take advantage of the styling capabilities and utilize the out-of-the-box interface that comes with it.

If you have any questions or feedback, or need help in bringing your app to Chromecast, simply send it to me at sonny@nowplayingapps.com.

The post How to choose the right chromecast receiver for your iOS app appeared first on Now Playing Apps.

]]>
147
Getting unstuck with iOS developer certificates and profiles https://nowplayingapps.com/ios-developer-certificates-and-profiles/ Tue, 02 Oct 2018 19:51:59 +0000 https://nowplayingapps.com/?p=69 Flow chart that describes what steps to take to acquire all necessary iOS developer certificates and profiles from your apple developer account.

The post Getting unstuck with iOS developer certificates and profiles appeared first on Now Playing Apps.

]]>
Whether you are new to iOS development or you are a seasoned developer, the process of figuring out your iOS developer certificates and profiles can get intimidating. Things are worse if you have to take over an existing project from another developer. You can spend hours, if not days chasing the profiles and certificates and P12 files etc.

I have gone through this many times, and finally decided to create this flow chart. You start from the top (where it says Start), and simply follow along. 

Flowchart - step by step guide to understand iOS developer certificates and profiles

If you have any questions or feedback, simply send it to me at sonny@nowplayingapps.com.

Hope you enjoy and happy coding!

The post Getting unstuck with iOS developer certificates and profiles appeared first on Now Playing Apps.

]]>
69
How to give more control to your users using MPNowPlayingInfoCenter https://nowplayingapps.com/how-to-give-more-control-to-your-users-using-mpnowplayinginfocenter/ Sat, 22 Sep 2018 18:28:58 +0000 https://nowplayingapps.com/?p=17 Building a video player to stream content is absolutely amazing, however your customer experience is only as good as how accurate the information that is presented to them. I have had challenges putting accurate data in front of the user, and here is how overcame this challenge when using AVPlayer in iOS apps.

The post How to give more control to your users using MPNowPlayingInfoCenter appeared first on Now Playing Apps.

]]>
Building an app that plays audio or video content? MPNowPlayingInfoCenter is a powerful API that Apple introduced (in iOS 5.0) that gives up to date information about your current playing content even if your app is backgrounded, or screen is locked. Let’s see what are the benefits of adding it to your app:

Benefits of adding NowPlayingInfo

  • Provide a quick overview of what your app is playing without opening your app
  • Includes all necessary metadata such as title, subtitle, start/end time, the artwork of current track and much more
  • Playback controls even if the app is in the background (such as play/pause, next/previous track)
  • Cast button to other airplay enabled devices
  • Visible on external devices (such as CarPlay) or other apple devices such as Apple TV or Apple Watch
  • Can be updated even if the app is running in the background

Let’s integrate

Alright, enough theory. Let’s dive in to see how your app can take advantage of this. MPNowPlayingInfoCenter has a singleton called NowPlayingInfo which is a dictionary where you can provide all this information (such as title, artist name, duration, artwork image etc.). That’s it! Easy as that. Let’s see it in code:

First things first. NowPlayingInfoCenter is part of MediaPlayer framework. So import it first like this:

import MediaPlayer

Alright, now lets us see what all properties are available to use.

var nowPlayingInfo = [String: Any]()
        
// prepare title and subtitle
nowPlayingInfo[MPMediaItemPropertyTitle] = "Movie Title"
nowPlayingInfo[MPMediaItemPropertyArtist] = "Artist Name"
        
// asynchronously download album art image.
// here, for simplicity, an image from asset catalog is loaded
if let albumArt = UIImage(named: "cover-art") {
    nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(boundsSize: albumArt.size, requestHandler: { imageSize in
        return albumArt
    })
}


If the current track is a live stream content (like news or a live event), you can take advantage of MPNowPlayingInfoPropertyIsLiveStream property.

// if playing item is a live stream. Default is false
nowPlayingInfo[MPNowPlayingInfoPropertyIsLiveStream] = true

To show current track duration and progress bar:

// Get asset duration from AVPlayerItem's AVAsset
// Duration is accurate only when AVPlayerItem.status == .readyToPlay.
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().seconds


Please note that playerItem.asset.duration is accurate only once AVPlayer/AVAudioPlayer has loaded the stream URL and is ready to play. In order to do this, it is recommended to observe AVPlayerItem’s status property and checking whether it is AVPlayerItem.Status.readyToPlay. Refer to my blog post to read more about this.

And finally, assign our nowPlayingInfo dictionary to MPNowPlayingInfoCenter like this:

// final step is to assign our dictionary to 
// MPNowPlayingInfoCenter singleton
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo


One last thing. In order for the show the nowplayinginfo on the notification screen, you need to add this one last piece of code inside your AppDelegate’s didFinishLaunchingWithOptions function.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     application.beginReceivingRemoteControlEvents()
}

And there you go! Here is how it would look on an iPhone 7 Plus device:

and if your app supports Apple CarPlay, this is how it looks:

NowplayingInfo Carplay

Conclusion

This is a great feature to take advantage of for your iOS streaming app and gives control and accessibility to your users. Happy streaming!

Check out our new upcoming service, RenewMyPush. With this, we hope to take the burden off you to update the push certificate manually. If this is something that you are interested in, let us know by visiting the service page, and we will let you know once this service is ready.

The post How to give more control to your users using MPNowPlayingInfoCenter appeared first on Now Playing Apps.

]]>
17