Sunday, July 20, 2014

Videos from youtube channel in iOS app (part 2)

We want to display list of channel's uploads. That list has an identifier, we need to find out, and it can be done with this request:
1. Channel details.

- (void) channelDetails {
   GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
   service.APIKey = API_KEY;
   GTLQueryYouTube *query = [GTLQueryYouTube queryForChannelsListWithPart:@"contentDetails"];
   query.forUsername = CHANNEL_NAME;
   [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
      if (!error) {
          GTLYouTubeChannelListResponse *items = object;
          for (GTLYouTubeChannelListResponse * item in items){
             NSLog(@"item: %@", item.JSON[@"contentDetails"]); 
          }
      } else{
           NSLog(@"%@", error);
      }
   }];
}


Response is in this format:

item: {
   googlePlusUserId = XXXXXXXXXX;
   relatedPlaylists = {
       uploads = "YYYYYYYYYYYYY";
   };
}

Store the value from "uploads" field to UPLOADS_LIST_ID.

2. List of uploaded videos. To receive list of uploaded videos we need to make a playlist items query with UPLOADS_LIST_ID as playlist id.


- (void) getUploads {
   GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];   service.APIKey = API_KEY;
   GTLQueryYouTube *query = [GTLQueryYouTube queryForPlaylistItemsListWithPart:@"id,snippet"];
   query.playlistId = UPLOADS_LIST_ID;
   query.maxResults = MAX_RESULTS; 
   [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
      if (!error) {
         GTLYouTubePlaylistItemListResponse *playlistItems = object;
         for (GTLYouTubePlaylistItem *playlistItem in playlistItems) {
            [self.identifiers addObject:playlistItem.snippet.resourceId.JSON[@"videoId"]];
         }
      [self getVideos];
     }else {
      NSLog(@"%@", error);
     }
   }];
}

3. List of uploaded videos with all information. Playlist queries, like one from above give us list of videos with details like: video id, title and thumbnail. To be able to read information like video duration and number of views, we need to make video list query. We can use list of video identifiers as filter for that query. For that reason we stored them in self.identifiers property of NSMutableDictionary type.

- (void) getVideos {
   GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
   service.APIKey = API_KEY;
   GTLQueryYouTube *query = [GTLQueryYouTube queryForVideosListWithPart:@"id, snippet, contentDetails, statistics, player"];
   query.identifier = [[self.identifiers valueForKey:@"description"] componentsJoinedByString:@","];
   [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error){
      if (!error) {
         GTLYouTubeVideoListResponse *videolistItems = object;
         for (GTLYouTubeVideo *videoItem in videolistItems){
            [self.dataSource addObject:videoItem];
         }
         [self.tableView reloadData]; 
      } else {
      NSLog(@"%@", error);
      }
   }];
}

You may also need query for list of playlists for fetching all information from one channel. For this query we will need CHANNEL_ID, not name.
4. List of channel's playlists:

- (void) loadPlaylists {
   GTLServiceYouTube *service = [[GTLServiceYouTube alloc] init];
   service.APIKey = API_KEY;
   GTLQueryYouTube *query = [GTLQueryYouTube queryForPlaylistsListWithPart:@"id, snippet, contentDetails"];
   query.channelId = CHANNEL_ID;
   query.maxResults = MAX_RESULTS;
   [service executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
      if (!error) {
         GTLYouTubePlaylistListResponse *items = object;
         for (GTLYouTubePlaylist * item in items) {
            [self.dataSource addObject:item];
         }
         [self.tableView reloadData];
      } else {
         NSLog(@"%@", error);
      }
   }];
}

Monday, June 30, 2014

Videos from youtube channel in iOS app (part 1)


1. Download Google Objective C Client. For developing any iOS application, that use some of Google APIs, we need to have Google libraries downloaded. In terminal run this command:
svn checkout http://google-api-objectivec-client.googlecode.com/svn/trunk/ google-api-objectivec-client-read-only
2. Build library. From downloaded items in Source folder open GTL.xcodeproj and choose iOS simulator and GTLTouchStaticLib as target. Then build library again, this time for iOS device. From Organizer>Products go to derived data by clicking arrow:


From Build>Products>Debug-iphoneos copy to e.g Desktop libGTLTouchStaticLib.a and rename it to e.g. libGTLTouchStaticLib1.a. Do the same for the file from Build>Products>Debug-iphonesimulator and rename it to libGTLTouchStaticLib2. With this command in Terminal, build fat static library


lipo -create -output libGTLTouchStaticLib.a libGTLTouchStaticLib1.a libGTLTouchStaticLib2.a


3. Adding source files for the library. Find header files in Source>Services>Youtube>Generated and add them to project (select: copy items into destination group's folder and create groups for any added folders). However, you don't need GTLYouTube_Sources.m file, so you should deleted it. From Derived Data folder: Build>Products>Debug-iphoneos add Headers folder to the project.

4. Adding frameworks and libraries. Add Security.framework, SystemConfiguration.framework and libGTLTouchStaticLib.a to project.

Now you can run your application on both iOS device and simulator, and start using Google Youtube API for fetching videos.

Wednesday, January 22, 2014

Sounds and notifications

If you are developing iOS application, with service that requires notifying users at specific time (e.g. alarms or utility applications like Power Nap), there are lot of specific issues regarding sounds, that you should be aware of. Setting custom notification sound is straightforward via soundName property of UILocalNotification object:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.soundName = @"melody.aiff";
1. The sound files must be in the main bundle of the client application. You can't use URLs e.g. from your iPod library to set custom sound. If your app still provide notifications with default sounds, you should check if the sound file is in the root directory of application project.

2. You can't set different system sound for notification. Either you don't specify sound, and notification sound will be default, or set sound from application bundle.

3. The sound must be aiff, wav, or caf file. You can't add .mp3 sounds for notification sound.

4. On iOS 7 it's possible that notification sound is off by default. 


One of the solutions mentions removing all code in your app that operates with applicationIconBadgeNumber. Now, your application should have notification sounds turned on by default, but you can test it only with new device, where you didn't previously install app.

5. If user switches phone to silent mode, notification sound will also be silent. In that case, there is no way to play sound when your app is in background.

6. Without explicit code, notification banner (with sound) will not show, when application is active (iOS 7). You can add code to display banner, or you could present custom view and play sound from application. This will work even if the phone is in silent mode.

Friday, July 19, 2013

Git Tips



This article is intended as a basic manual for iOS developers that are using git source control, but need more than built in options in xCode.

For that we will need to open Terminal application located in Applications/Utilities. Use 'ls' command to see content of the current folder, and 'cd FOLDER_NAME' to open specific subfolder. Command 'cd ..' will open parent folder.

If you want to simply clone repository from remote repository then run this command in your terminal:
git clone HTTPS_ORIGINAL_REMOTE_REPOSITORY.git
This will clone project to the current folder.

Second scenario is that you want to add existing project to remote repository. Go to the folder that contains your .xcodeproj project file.

To check current status:
git status
When your code is already tracked by Git, and you want to change the repository, you have two options.

1. Remove git tracking and start fresh:
rm -rf .git
2. Set new repository as your origin to push to.
git remote set-url origin HTTPS_NEW_REMOTE_REPOSITORY.git
To start git tracking, initialize empty git
git init
Next step is to add original remote repository, which you acquire at your git hosting service, e.g. Bitbucket
git remote add origin HTTPS_ORIGINAL_REMOTE_REPOSITORY.git
Add all files from your project directory
git add --all
Commit
git commit -m "Initial Commit"
Push
git push origin master
Your project is now pushed to remote repository.