Online Formatter

HTML Formatter
http://codebeautify.org/htmlviewer/
http://www.cleancss.com/html-beautify/
http://www.freeformatter.com/html-formatter.html

Questions inside:
What is a protocol?
How do you submit an app to the app store?
What is ARC?
What is an app bundle?
When would you use a swift struct vs class?
What is pass by value vs pass by type?
How do you create a custom view?
How to do http requests and parse JSON?
What do you use to show a list of data on the screen?
What is polymorphism?
What is UIWindow? UIApplication?
Difference between viewDidLoad and viewWillAppear?
What is NSNotificationCenter? Delegates?
How do threads work in iOS?
Diff between XIBs and Storyboard files?

————————————
xxthermidorxx/qr-code-reader
https://github.com/xxthermidorxx/qr-code-reader
smmarat/QrReader
https://github.com/smmarat/QrReader
martin-kubik/Advanced-QR-Code-reader
https://github.com/martin-kubik/Advanced-QR-Code-reader
TechSmith/android-quick-response-code
https://github.com/TechSmith/android-quick-response-code
Gnzlt/AndroidVisionQRReader
https://github.com/Gnzlt/AndroidVisionQRReader
sasidhar678/Bar-QR-Code-Reader-Android-App
https://github.com/sasidhar678/Bar-QR-Code-Reader-Android-App
SuyashLakhotia/SimpleQRCodeReader
https://github.com/SuyashLakhotia/SimpleQRCodeReader
evanisnor/Camera2Basic
https://github.com/evanisnor/Camera2Basic
georgejenkins/WelcomeHome
https://github.com/georgejenkins/WelcomeHome
————————————
pratikone/AndrOCR—Android-based-OCR-app
https://github.com/pratikone/AndrOCR—Android-based-OCR-app
ivorycirrus/NFC-Secret-Note
https://github.com/ivorycirrus/NFC-Secret-Note
cpalosrejano/android-share-facebook
https://github.com/cpalosrejano/android-share-facebook
r-ashish/myOCR
https://github.com/r-ashish/myOCR
kamcpp/rss-reader-android-app
https://github.com/kamcpp/rss-reader-android-app
————————————
Android Take Photo From Camera and Gallery – Code Sample
http://www.theappguruz.com/blog/android-take-photo-camera-gallery-code-sample
How To Integrate PayPal in Android
http://www.theappguruz.com/blog/integrate-paypal-in-android
Android – Text to PDF
http://www.theappguruz.com/blog/android-text-pdf
Android – Send SMS using SmsManager API
http://www.theappguruz.com/blog/android-send-sms-using-smsmanager-api
Hide Secrets – for Secret Pics, SMS, Apps for Android Phone
http://www.theappguruz.com/blog/hide-secrets-secret-pics-sms-apps-android-phone
External JAR as Dependency in Android Studio
http://www.theappguruz.com/blog/external-jar-dependency-android-studio
theappguruz/Android-Take-Photo-From-Camera-and-Gallery-Code-Sample
https://github.com/theappguruz/Android-Take-Photo-From-Camera-and-Gallery-Code-Sample
How to make intent chooser for camera or gallery application in android like whatsapp editprofile?
http://stackoverflow.com/questions/27874038/how-to-make-intent-chooser-for-camera-or-gallery-application-in-android-like-wha
Android – How to take a picture from camera or gallery
http://stackoverflow.com/questions/20021431/android-how-to-take-a-picture-from-camera-or-gallery
Single intent to let user take picture OR pick image from gallery in Android
http://stackoverflow.com/questions/2708128/single-intent-to-let-user-take-picture-or-pick-image-from-gallery-in-android
Allow user to select camera or gallery for image
http://stackoverflow.com/questions/4455558/allow-user-to-select-camera-or-gallery-for-image
Fetch Image from Camera or Gallery – Android
http://myandroidtuts.blogspot.com/2013/05/fetch-image-from-camera-or-gallery.html
————————————

URL Address (Android)


Android

https://github.com/tdaiku/CustomGridTableViewController


Rz Rasel


Rz Rasel

URL Address (iOS)


iOS Swift

https://github.com/tdaiku/CustomGridTableViewController


Swift UITableView: Load data from JSON

In this tutorial I’ll explain you how to fill an iOS UITableView component by loadingthe data directly from an URL using the JSON format. You’ll see how to define a tableview controller in swift, how to load the data from URL and how to extract the data from the JSON format.

Define the project

Let’s create a new Swift iOS single view project.

 

In the Main.storyboard you can disable the use size classes option.

 

Now you can remove the View controller that is inside the storyboard as default, we don’t need that!

 

Define the layout and the custom classes

In the Main.storyboard you’ve to add the UITableViewController element.

 

Now you’ve to set a custom class for the UITableViewController that allows you to manage the data that will be displayed.

Create a new iOS Cocoa Touch Class and set the subclass asUITableViewController and the name of the class as TableController and create it.

Swift: add custom class

 

Now in the Main.storyboard select again your UITableViewController and in the identity inspector set the TableController class that you’ve prevously created.

Swift: set custom class

 

In the Attribute inspector turn on the is initial view controller option.

Swift: is initial controller

 

Now you have to select the table view cell and under the attribute inspector set the identifier to cell.

Swift: cell identifier

 

TableController custom class

Now you’ve to implement the table controller class. This class is the core of the table. Here you’ll define the download function, the json extractor function and finally the cell definition.

The first thing you’ve to do is to define the array that will be used to store and read the data. Let’s define the TableData String array as:

var TableData:Array< String > = Array < String >()

The viewDidLoad() is the function that will be called as soon as the view has been loaded. Inside it you should call the get_data_from_url function. We will define this function later, but let’s add the function call placeholder.

var TableData:Array< String > = Array < String >()
override func viewDidLoad() {
      super.viewDidLoad()
      get_data_from_url("http://www.kaleidosblog.com/tutorial/tutorial.json")
}

At this link I’ve prepared for you a json object. This is a simple list of countries and countries’ codes. If you want use this easy tool to explore this structure in a readable format.

Set the number of sections to 1 and the number of rows to the array’s size.

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
     return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     return TableData.count
}

Configure now the cell to load the array string at the position defined by the indexPath object. The “cell” identifier is the same identifier name that you previously set for the cell element. The cellForRowAtIndexPath function is called for every cell that is visible on the screen at a particular moment. So, for example, if you have to load 200 cells on your table, this function is called only 10-15 times, that’s because only the elements that have to be displayed are loaded. Every time you scroll your table, this function is called again for the items that have to be displayed.
In this case we’ll use the textlabel that is defined in the default cell layout.

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
     cell.textLabel?.text = TableData[indexPath.row]
     return cell
}

let’s define now the get_data_from_url function by exploiting theiOS asynchronous call.

func get_data_from_url(url:String)
{
    let httpMethod = "GET"
    let timeout = 15
    let url = NSURL(string: url)
    let urlRequest = NSMutableURLRequest(URL: url!,
    cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
    timeoutInterval: 15.0)
    let queue = NSOperationQueue()
    NSURLConnection.sendAsynchronousRequest(
                                  urlRequest,
                                  queue: queue,
                                  completionHandler: {(response: NSURLResponse!,
                                                                   data: NSData!,
                                                                   error: NSError!) in
             if data.length > 0 && error == nil{
                 self.extract_json(data!)
             }else if data.length == 0 && error == nil{
                 println("Nothing was downloaded")
             } else if error != nil{
                 println("Error happened = \(error)")
             }
         }
     )
}

When the get_data_from_url function has done the download of the json data, the extract_json function is called. Let’s now implement it. This function will extract the json data and fill the TableData array. In a JSON format there are two different main types: the array and the objects. Arrays are identified by the [ ] brackets while the object are identified by the { } brackets. This two types in Swift are defined by NSArray and NSDictionary respectively. For every JSON object you’ve to define a safe variable (using let and the question mark) with the right type. The json used in this example has this structure:

array
Object
name (String)
code (String)

Object
name (String)
code (String)

Let’s now implement the extract_json function.

func extract_json(jsonData:NSData)
{
     var parseError: NSError?
     let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &parseError)
     if (parseError == nil)
     {
        if let countries_list = json as? NSArray
        {
           for (var i = 0; i < countries_list.count ; i++ )
           {
               if let country_obj = countries_list[i] as? NSDictionary
               {
                   if let country_name = country_obj["country"] as? String
                   {
                       if let country_code = country_obj["code"] as? String
                       {
                             TableData.append(country_name + " [" + country_code + "]")
                       }
                   }
                }
            }
        }
     }
     do_table_refresh();
}

 

Finally we have the data into our TableData array, we only have to refresh the table in the main thread.

func do_table_refresh()
{
     dispatch_async(dispatch_get_main_queue(), {
         self.tableView.reloadData()
        return
     })
}

 

You can download the code for this example here.
UPDATE: download the swift 2 code example from here

Swift: TableView tutorial

Reference Reference

Remote JSON Data to tableView in iOS (Swift)

import UIKit
import Foundation
import XCPlayground

XCPSetExecutionShouldContinueIndefinitely()

class RemoteAPI {
    func getData(completionHandler: ((NSArray!, NSError!) -> Void)!) -> Void {
        let url: NSURL = NSURL(string: "http://itunes.apple.com/search?term=Turistforeningen&media=software")
        let ses = NSURLSession.sharedSession()
        let task = ses.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
            if (error != nil) {
                return completionHandler(nil, error)
            }

            var error: NSError?
            let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
            
            if (error != nil) {
                return completionHandler(nil, error)
            } else {
                return completionHandler(json["results"] as [NSDictionary], nil)
            }
        })
        task.resume()
    }
}

var api = RemoteAPI()

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    var tableView: UITableView!
    var items: NSMutableArray = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
        self.tableView = UITableView(frame:self.view!.frame)
        self.tableView!.delegate = self
        self.tableView!.dataSource = self
        self.tableView!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
        self.view?.addSubview(self.tableView)
        
        api.getData({data, error -> Void in
            if (data != nil) {
                self.items = NSMutableArray(array: data)
                self.tableView!.reloadData()
                self.view
            } else {
                println("api.getData failed")
                println(error)
            }
        })
    }
    
    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        return self.items.count;
    }

    func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
        
        if let navn = self.items[indexPath.row]["trackName"] as? NSString {
            cell.textLabel.text = navn
        } else {
            cell.textLabel.text = "No Name"
        }
        
        if let desc = self.items[indexPath.row]["description"] as? NSString {
            cell.detailTextLabel.text = desc
        }
        
        return cell
    }
}

ViewController().view

OR:-

import UIKit

class TableViewController: UITableViewController {

var tableName = [String]()
var tableID = [String]()
override func viewDidLoad() {
    super.viewDidLoad()
    getContactListJSON()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func getContactListJSON(){
    let urlString = "http://jsonplaceholder.typicode.com/users"
    let urlEncodedString = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
    let url = NSURL( string: urlEncodedString!)
    var task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, innerError) in
        let json = JSON(data: data)
        let contactsArray = json.arrayValue

        dispatch_async(dispatch_get_main_queue(), {
            for contacts in contactsArray
            {
                let id = contacts["id"].stringValue
                let name = contacts["name"].stringValue
                println( "id: \(id) name: \(name)" )
                self.tableName.append(name)
                self.tableID.append(id)
            }
            dispatch_async(dispatch_get_main_queue(),{
                self.tableView.reloadData()
            })
        })
    }
    task.resume()
}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableName.count
}


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TableViewCell

    // Configure the cell...
    cell.id.text = tableID[indexPath.row]
    cell.name.text = tableName[indexPath.row]
    return cell

    }
}

Youtube Integration In Android Studio

The YouTube Android Player API enables you to incorporate video playback functionality into your Android applications. The API allows you to load and play YouTube videos (and playlists) and to customize and control the video playback experience.

You can load or cue videos into a player view embedded in your application’s UI. You can then control playback programmatically. For example play, pause, or seek to a specific point in the loaded video. You can register event listeners to get callbacks for certain events, such as the player loading a video or the player state changing. The API also has helper functionality to support orientation changes as well as transitions to fullscreen playback.

To get started, create a new project. I called mine VideoTube. In the Next screens of the Android Studio wizard select API 10, Blank Activity and MainActivity as the activity name.

Before using the Android Youtube API, you need to register your application, including your digitally signed .apk file’s public certificate in the Google Developers Console. To register the application, follow these steps.

  1. Go to the Google Developers Console
  2. Create a new project. I named mine VideoTube.
  3. On the page that appears after project creation, expand APIs & auth on the left sidebar. Next, click APIs. In the list of APIs, click on YouTube Data API and enable the Youtube Data API v3 on the page that follows.
  4. In the sidebar on the left, select Credentials. For credentials, the API supports OAuth 2.0, the use of an API key and of a Service account. We’ll use the API key option.
  5. Select API key from the Add Credentials dropdown menu. A popup will appear for you to specify the key type. Select Android Key. Next select Add package name and fingerprint and add the Android app’s package name (Mine is com.echessa.videotube) and then run the following command in Terminal to get the SHA-1 certificate fingerprint.
keytool -list -v -keystore ~/.android/debug.keystore

Enter android as the password when prompted. The above command prints information on the debug keystore that is located at ~/.android/debug.keystore on your computer. This was generated automatically by Eclipse or Android Studio when you first built an Android app. In the Terminal, you will see the MD5 and SHA-1 certificate fingerprints. Copy the SHA-1 fingerprint and paste it on the Google Developer Console and click on the Create button. An API key will be generated. We’ll use this later.

Back in the Android app, create a class named Config.java and paste in the following.

package com.echessa.videotube;

/**
 * Created by echessa on 7/17/15.
 */
public final class Config {

    private Config() {
    }

    public static final String YOUTUBE_API_KEY = "YOUR API KEY";

}

Paste in your API key.

Download the latest version of the YouTube Android Player API (1.2.1 at the time of writing). Unzip the downloaded file to find the library jar file and a sample application that you can use to see what the library offers. The jar file is located in the libs folder. Copy and paste it into your project’s libs folder. To access the libs folder, use the Project perspective on the Android Studio Project Explorer. Then expand VideoTube -> app -> libs.

Project Explorer

Change back to the Android perspective, select the build.gradle (Module: app) file and add the following to the dependencies.

compile files('libs/YouTubeAndroidPlayerApi.jar')

Sync the project’s gradle files.

Add the following permission for internet access to the AndroidManifest.xml file as a child of the manifest tag and a sibling to the application.

<uses-permission android:name="android.permission.INTERNET"/>

Edit the strings.xml file as shown. These are all the string resources we’ll require.

<resources>
    <string name="app_name">VideoTube</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="player_error">Error initializing YouTube player</string>
    <string name="seek_to">Jump To</string>
    <string name="seek_to_hint">Seconds</string>
</resources>

Next we’ll add a YouTubePlayerView to the layout file. This view is used for displaying YouTube videos.

Modify activity_main.xml as shown.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>

We’ll be using the YouTubePlayerView directly in our activity as opposed to using the YouTubePlayerFragment. Because of this, the activity needs to extend the YouTubeBaseActivity class.

Modify MainActivity.java as shown.

package com.echessa.videotube;

import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.google.android.youtube.player.YouTubeBaseActivity;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayer.Provider;
import com.google.android.youtube.player.YouTubePlayerView;

public class MainActivity extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener {

    private static final int RECOVERY_REQUEST = 1;
    private YouTubePlayerView youTubeView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
        youTubeView.initialize(Config.YOUTUBE_API_KEY, this);
    }

    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
        if (!wasRestored) {
            player.cueVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
        }
    }

    @Override
    public void onInitializationFailure(Provider provider, YouTubeInitializationResult errorReason) {
        if (errorReason.isUserRecoverableError()) {
            errorReason.getErrorDialog(this, RECOVERY_REQUEST).show();
        } else {
            String error = String.format(getString(R.string.player_error), errorReason.toString());
            Toast.makeText(this, error, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RECOVERY_REQUEST) {
            // Retry initialization if user performed a recovery action
            getYouTubePlayerProvider().initialize(Config.YOUTUBE_API_KEY, this);
        }
    }

    protected Provider getYouTubePlayerProvider() {
        return youTubeView;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}

In the above code, we created a class that is a subclass of YouTubeBaseActivity. This is required to make use of YouTubePlayerView. We implemented YouTubePlayer.OnInitializedListener to listen for initialization success or failure. The interface has two methods, named onInitializationFailure() and onInitializationSuccess(). If initialization is successful, the cueVideo() method plays the YouTube video and incase of failure, checks to see whether the error is recoverable by user action.

If it’s not then a Toast of the error is shown to the user and if it’s user-recoverable, then the getErrorDialog() method shows a dialog that will enable the user to recover from the error.

For example, if the YouTube app isn’t installed on the user’s device or is out of date, the dialog will have a prompt that upon confirmation, will open the Google Play Store for the user to install or update it accordingly. If the YouTube app is disabled on the device, then the prompt will open System Settings for the user to enable it.

When the user returns from the error recovery dialog, onActivityResult() is called checks to see if the user performed a recovery action. If so, we retry initialization.

Run the app and you should be able to play the video specified in the code. Note that you will need the YouTube app on your device. The API client library interacts with a service that is distributed as part of the YouTube app for the Android platform. Users need to run version 4.2.16 of the mobile YouTube app (or higher) to use the API. Generally, devices running Android 2.2 (Froyo) or later that have the Google Play Store app should be able to run the up-to-date version of the YouTube app.

What this means, is that unless you have installed Google Apps on your virtual device, you won’t be able to test the code on the emulator. The default Android emulator doesn’t support installing Google Apps on the device, but if you use an emulator like Genymotion you will be able to (despite the team discontinuing support for Google Apps). Even with Google Apps installed on my emulator, I still could not play the video. The video thumbnail loaded okay on the view, but upon tapping the Play button, a loading indicator would appear, but then loading would fail with a message of ‘Connection to server lost’. You probably need a real device for this.

YouTube Player

Responding to Playback Events and State Changes

In the app, you might need to take some action depending on the YouTube player’s events such as buffering, play, pause, seek and stop. You might want to show the user a message or overlay the player view with another view once video playback stops or ends.

The YouTubePlayer has the following interface definitions to listen to such events:

  • YouTubePlayer.PlayerStateChangeListener – Interface definition for callbacks which invoked when the high level player state changes.
  • YouTubePlayer.PlaybackEventListener – Interface definition for callbacks which invoked when video playback events occur.
  • YouTubePlayer.OnFullscreenListener – Interface definition for callbacks which invoked when the player toggles between fullscreen on or off, either due to the user clicking the fullscreen button or a call to setFullscreen(boolean).
  • YouTubePlayer.PlaylistEventListener – Interface definition for callbacks which invoked when events related to playlists occur.

We will look at the first two for this app.

Add the following method to the MainActivity class.

private void showMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}

This will create a Toast with the message passed into the function. This will save us from writing similar lines of code.

Next add the following two subclasses to the MainActivity class.

private final class MyPlaybackEventListener implements YouTubePlayer.PlaybackEventListener {

    @Override
    public void onPlaying() {
        // Called when playback starts, either due to user action or call to play().
        showMessage("Playing");
    }

    @Override
    public void onPaused() {
        // Called when playback is paused, either due to user action or call to pause().
        showMessage("Paused");
    }

    @Override
    public void onStopped() {
        // Called when playback stops for a reason other than being paused.
        showMessage("Stopped");
    }

    @Override
    public void onBuffering(boolean b) {
        // Called when buffering starts or ends.
    }

    @Override
    public void onSeekTo(int i) {
        // Called when a jump in playback position occurs, either
        // due to user scrubbing or call to seekRelativeMillis() or seekToMillis()
    }
}

private final class MyPlayerStateChangeListener implements YouTubePlayer.PlayerStateChangeListener {

    @Override
    public void onLoading() {
        // Called when the player is loading a video
        // At this point, it's not ready to accept commands affecting playback such as play() or pause()
    }

    @Override
    public void onLoaded(String s) {
        // Called when a video is done loading.
        // Playback methods such as play(), pause() or seekToMillis(int) may be called after this callback.
    }

    @Override
    public void onAdStarted() {
        // Called when playback of an advertisement starts.
    }

    @Override
    public void onVideoStarted() {
        // Called when playback of the video starts.
    }

    @Override
    public void onVideoEnded() {
        // Called when the video reaches its end.
    }

    @Override
    public void onError(YouTubePlayer.ErrorReason errorReason) {
        // Called when an error occurs.
    }
}

The above creates classes that implement the YouTubePlayer.PlaybackEventListener and YouTubePlayer.PlayerStateChangeListener interfaces. For each class, I have implemented the interface methods and included a comment of when the callback is invoked. You can take whatever action you want in each callback. For our example, I have included a Toast output for the onPlaying(), onPaused() and onStopped() methods that will output a message when the event happens.

Add the following class variables to the MainActivity file.

private MyPlayerStateChangeListener playerStateChangeListener;
private MyPlaybackEventListener playbackEventListener;

Add the following to the bottom of onCreate() to initialize the above objects.

playerStateChangeListener = new MyPlayerStateChangeListener();
playbackEventListener = new MyPlaybackEventListener();

Modify onInitializationSuccess() as shown. This sets the listeners on the YouTubePlayer object.

@Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean wasRestored) {
    player.setPlayerStateChangeListener(playerStateChangeListener);
    player.setPlaybackEventListener(playbackEventListener);

    if (!wasRestored) {
        player.cueVideo("fhWaJi1Hsfo"); // Plays https://www.youtube.com/watch?v=fhWaJi1Hsfo
    }
}

Run the app and you should see different Toast messages appear when you start playing the video, when you pause it and when it stops (for a reason other than being paused, e.g. the video ending or a playback error).

Custom Player Controls

The YouTube library does a good job of creating an out-of-the-box user friendly interface to play YouTube videos. As a developer, you might want to take this further and provide custom controls that will give the user more control over playback. For example, enable them to jump back and forth in the video, or enable them to play the next or previous video in a playlist.

We’ll create a control in our app that will enable the user to jump to a specific time in the video.

The API provides two methods to jump playback:

  • seekToMillis() – Seeks to the specified time in the video.
  • seekRelativeMillis() – Seeks forward or backwards by the specified number of seconds.

We’ll use the first to jump to a specified time in the video.

Modify activitymain.xml_ as shown.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context=".MainActivity">

    <com.google.android.youtube.player.YouTubePlayerView
        android:id="@+id/youtube_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/seek_to_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:hint="@string/seek_to_hint"/>

        <Button
            android:id="@+id/seek_to_button"
            android:text="@string/seek_to"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</LinearLayout>

In MainActivity add the following class variable.

private YouTubePlayer player;

In onInitializationSuccess() set this variable.

this.player = player;

Add the following to the bottom of onCreate().

final EditText seekToText = (EditText) findViewById(R.id.seek_to_text);
    Button seekToButton = (Button) findViewById(R.id.seek_to_button);
    seekToButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int skipToSecs = Integer.valueOf(seekToText.getText().toString());
            player.seekToMillis(skipToSecs * 1000);
        }
    });

Run the app and you should be able to enter a number (in seconds) and have the video skip to that point. If you input a number that is larger than the duration of the video, then the video will skip to the end.

Conclusion

In this tutorial, we have looked at how to embed a YouTube player in your app. This is handy if you want your app users to be able to play YouTube videos while remaining in your app, instead of the YouTube app opening to play the video and then the user returning to your app after playback.

The YouTube Android library provides a great API that enables you to customise this experience and we’ve only touched on its capabilities. To find out more about the library, be sure to read through the documentation and the sample app that comes with the library download.

You can download the completed project here. Remember to place your key in the Config.java file.

I’d be keen to hear if you try the tutorial and your experiences and any questions you may have.

http://www.sitepoint.com/using-the-youtube-api-to-embed-video-in-an-android-app/

Android Custom Material Design Theme and Color

Google has introduced a new design guideline with the release of Android 5.0 (Lollipop) known as Material Design, and with this guidelines Google provide Material Theme to the android developer. This is a new user interface. In this post, I will show you way to use custom material design theme and color in your application.

Setup Material Theme

First of all, you have to setup material design theme to your styles.xml file. You can choose any of three material themes according to your wish:
• Theme.Material
• Theme.Material.Light
• Theme.Material.Light.DarkActionBar
Here I have used Theme.Material.Light.DarkActionBar as app theme.

    <style name="AppTheme" parent="Theme.Material.Light.DarkActionBar">
</style>

 

Add Custom Theme Colors

You have to create a colors.xml file in res/values folder to define custom theme colors. After defining theme colors, your colors.xml file seems like this.
res/values/colors.xml

<?xml version=1.0 encoding=utf-8?>
<resources>
<color name=colorPrimary>#03A9F4</color>
<color name=colorPrimaryDark>#0288D1</color>
<color name=colorAccent>#00BCD4</color>
<color name=windowBackground>#fff</color>
<color name=navigationBarColor>#0288D1</color>
<color name=statusBarColor>#0288D1</color>
<color name=textColorPrimary>#fff4f4f4</color>
</resources>
view raw colors.xml hosted with ❤ by GitHub

 

Look at following image, here I have shown meaning of colorPrimary, colorPrimaryDark, colorAccent, windowBackground, navigationBarColor, statusBarColor, textColorPrimary.

Android Custom Material Design Theme and Color

 

Update Your styles.xml File

Here, I have added status bar color, action bar / app bar color, app background color, navigation bar color, etc. that we defined before in our colors.xml file. Your styles.xml file seems like this.
res/values/styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.Material.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowBackground">@color/windowBackground</item>
        <item name="android:navigationBarColor">@color/navigationBarColor</item>
        <item name="android:statusBarColor">@color/statusBarColor</item>
        <item name="android:textColorPrimary">@color/textColorPrimary</item>
        <!-- Customize your theme here. -->
    </style>

</resources>

Only this much is not about the material design, it is lot more. Here I just described how to use custom material design theme and color in android application. For more about android material

http://www.viralandroid.com/2015/08/android-custom-material-design-theme-color.html

Image in Sqlite Database and display in a List | SqLite demo in Android

Hello Friends,
      Today I am going to share very important example for how to save Image and text in Sq-lite database and how to display it in a List-view. Steps and code are given below please follow-
1- Create a new Project name e.g.- SQLiteImageDemo.
2- Create a DataBaseHandler class and create database.
3-Create a SQLiteDemoActivity and call DatabaseHandler class for insert and get data from database.
4- Create a Contact class.
4- Create a ContactImageAdapter class for create custom ListView.
5-Add ListView in main.xml file.
6-Create a xml file for add Image and Text.
a) Print Screen:
b)DataBaseHandler.java
package com.manish.sqlite;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = “imagedb”;
// Contacts table name
private static final String TABLE_CONTACTS = “contacts”;
// Contacts Table Columns names
private static final String KEY_ID = “id”;
private static final String KEY_NAME = “name”;
private static final String KEY_IMAGE = “image”;
public DataBaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = “CREATE TABLE ” + TABLE_CONTACTS + “(“
+ KEY_ID + ” INTEGER PRIMARY KEY,” + KEY_NAME + ” TEXT,”
+ KEY_IMAGE + ” BLOB” + “)”;
db.execSQL(CREATE_CONTACTS_TABLE);
}
// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL(“DROP TABLE IF EXISTS ” + TABLE_CONTACTS);
// Create tables again
onCreate(db);
}
/**
* All CRUD(Create, Read, Update, Delete) Operations
*/
public// Adding new contact
void addContact(Contact contact) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, contact._name); // Contact Name
values.put(KEY_IMAGE, contact._image); // Contact Phone
// Inserting Row
db.insert(TABLE_CONTACTS, null, values);
db.close(); // Closing database connection
}
// Getting single contact
Contact getContact(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID,
KEY_NAME, KEY_IMAGE }, KEY_ID + “=?”,
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getBlob(1));
// return contact
return contact;
}
// Getting All Contacts
public List<Contact> getAllContacts() {
List<Contact> contactList = new ArrayList<Contact>();
// Select All Query
String selectQuery = “SELECT * FROM contacts ORDER BY name”;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Contact contact = new Contact();
contact.setID(Integer.parseInt(cursor.getString(0)));
contact.setName(cursor.getString(1));
contact.setImage(cursor.getBlob(2));
// Adding contact to list
contactList.add(contact);
} while (cursor.moveToNext());
}
// close inserting data from database
db.close();
// return contact list
return contactList;
}
// Updating single contact
public int updateContact(Contact contact) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, contact.getName());
values.put(KEY_IMAGE, contact.getImage());
// updating row
return db.update(TABLE_CONTACTS, values, KEY_ID + ” = ?”,
new String[] { String.valueOf(contact.getID()) });
}
// Deleting single contact
public void deleteContact(Contact contact) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_CONTACTS, KEY_ID + ” = ?”,
new String[] { String.valueOf(contact.getID()) });
db.close();
}
// Getting contacts Count
public int getContactsCount() {
String countQuery = “SELECT * FROM ” + TABLE_CONTACTS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
cursor.close();
// return count
return cursor.getCount();
}
}
c)SQLiteDemoActivity.java
package com.manish.sqlite;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;
public class SQLiteDemoActivity extends Activity {
ArrayList<Contact> imageArry = new ArrayList<Contact>();
ContactImageAdapter adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
DataBaseHandler db = new DataBaseHandler(this);
// get image from drawable
Bitmap image = BitmapFactory.decodeResource(getResources(),
R.drawable.facebook);
// convert bitmap to byte
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte imageInByte[] = stream.toByteArray();
/**
* CRUD Operations
* */
// Inserting Contacts
Log.d(“Insert: “, “Inserting ..”);
db.addContact(new Contact(“FaceBook”, imageInByte));
// display main List view bcard and contact name
// Reading all contacts from database
List<Contact> contacts = db.getAllContacts();
for (Contact cn : contacts) {
String log = “ID:” + cn.getID() + ” Name: ” + cn.getName()
+ ” ,Image: ” + cn.getImage();
// Writing Contacts to log
Log.d(“Result: “, log);
//add contacts data in arrayList
imageArry.add(cn);
}
adapter = new ContactImageAdapter(this, R.layout.screen_list,
imageArry);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
}
}
d)Contact.java
package com.manish.sqlite;
public class Contact {
// private variables
int _id;
String _name;
byte[] _image;
// Empty constructor
public Contact() {
}
// constructor
public Contact(int keyId, String name, byte[] image) {
this._id = keyId;
this._name = name;
this._image = image;
}
// constructor
public Contact(String name, byte[] image) {
this._name = name;
this._image = image;
}
// getting ID
public int getID() {
return this._id;
}
// setting id
public void setID(int keyId) {
this._id = keyId;
}
// getting name
public String getName() {
return this._name;
}
// setting name
public void setName(String name) {
this._name = name;
}
// getting phone number
public byte[] getImage() {
return this._image;
}
// setting phone number
public void setImage(byte[] image) {
this._image = image;
}
}
e)ContactImageAdapter.java
package com.manish.sqlite;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ContactImageAdapter extends ArrayAdapter<Contact>{
Context context;
int layoutResourceId;
ArrayList<Contact> data=new ArrayList<Contact>();
public ContactImageAdapter(Context context, int layoutResourceId, ArrayList<Contact> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ImageHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ImageHolder();
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
row.setTag(holder);
}
else
{
holder = (ImageHolder)row.getTag();
}
Contact picture = data.get(position);
holder.txtTitle.setText(picture ._name);
//convert byte to bitmap take from contact class
byte[] outImage=picture._image;
ByteArrayInputStream imageStream = new ByteArrayInputStream(outImage);
Bitmap theImage = BitmapFactory.decodeStream(imageStream);
holder.imgIcon.setImageBitmap(theImage);
return row;
}
static class ImageHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}
f)main.xml
<?xml version=“1.0” encoding=“utf-8”?>
<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android&#8221;
android:layout_width=“fill_parent”
android:layout_height=“fill_parent”
android:orientation=“vertical” >
<ListView
android:id=“@+id/list”
android:layout_width=“fill_parent”
android:layout_height=“0dp”
android:layout_weight=“0.55” >
</ListView>
</LinearLayout>
g)screen_list.xml
<?xml version=“1.0” encoding=“utf-8”?>
<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android&#8221;
android:layout_width=“fill_parent”
android:layout_height=“fill_parent”
android:orientation=“horizontal”
android:padding=“10dp” >
<ImageView
android:id=“@+id/imgIcon”
android:layout_width=“0dp”
android:layout_height=“100dp”
android:layout_weight=“0.71”
android:gravity=“center_vertical” />
<TextView
android:id=“@+id/txtTitle”
android:layout_width=“80dp”
android:layout_height=“fill_parent”
android:gravity=“center_vertical”
android:textSize=“14dp”
android:layout_marginLeft=“7dp” />
</LinearLayout>
For simple sqlite demo you can refer below link-
http://www.androidhub4you.com/2012/09/sqlite-database-in-android.html

Custom Calendar in Android | Android Calendar Example with full source code

Hello dear friends,
Today I am going to share very Important code for custom calender in Android.
Actually android not provide any calender view so its a very big draw back for developer but we can create a custom calender using grid-view.Important step is given below-
1- Create new project e.g.-CustomCalenderAndroid
2- Create an activity MyCalendarActivity.java
3- Create layout my_calendar_view.xml
4- Create another xml file screen_gridcell.xml
5- Add styles_calendar_events.xml in values folder
6- Add Images for calendar in drawable folder

1-Print Screen:

2-MyCalendarActivity.java

package com.examples;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

@TargetApi(3)
public class MyCalendarActivity extends Activity implements OnClickListener {
 private static final String tag = "MyCalendarActivity";

 private TextView currentMonth;
 private Button selectedDayMonthYearButton;
 private ImageView prevMonth;
 private ImageView nextMonth;
 private GridView calendarView;
 private GridCellAdapter adapter;
 private Calendar _calendar;
 @SuppressLint("NewApi")
 private int month, year;
 @SuppressWarnings("unused")
 @SuppressLint({ "NewApi", "NewApi", "NewApi", "NewApi" })
 private final DateFormat dateFormatter = new DateFormat();
 private static final String dateTemplate = "MMMM yyyy";

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.my_calendar_view);

  _calendar = Calendar.getInstance(Locale.getDefault());
  month = _calendar.get(Calendar.MONTH) + 1;
  year = _calendar.get(Calendar.YEAR);
  Log.d(tag, "Calendar Instance:= " + "Month: " + month + " " + "Year: "
    + year);

  selectedDayMonthYearButton = (Button) this
    .findViewById(R.id.selectedDayMonthYear);
  selectedDayMonthYearButton.setText("Selected: ");

  prevMonth = (ImageView) this.findViewById(R.id.prevMonth);
  prevMonth.setOnClickListener(this);

  currentMonth = (TextView) this.findViewById(R.id.currentMonth);
  currentMonth.setText(DateFormat.format(dateTemplate,
    _calendar.getTime()));

  nextMonth = (ImageView) this.findViewById(R.id.nextMonth);
  nextMonth.setOnClickListener(this);

  calendarView = (GridView) this.findViewById(R.id.calendar);

  // Initialised
  adapter = new GridCellAdapter(getApplicationContext(),
    R.id.calendar_day_gridcell, month, year);
  adapter.notifyDataSetChanged();
  calendarView.setAdapter(adapter);
 }

 /**
  * 
  * @param month
  * @param year
  */
 private void setGridCellAdapterToDate(int month, int year) {
  adapter = new GridCellAdapter(getApplicationContext(),
    R.id.calendar_day_gridcell, month, year);
  _calendar.set(year, month - 1, _calendar.get(Calendar.DAY_OF_MONTH));
  currentMonth.setText(DateFormat.format(dateTemplate,
    _calendar.getTime()));
  adapter.notifyDataSetChanged();
  calendarView.setAdapter(adapter);
 }

 @Override
 public void onClick(View v) {
  if (v == prevMonth) {
   if (month <= 1) {
    month = 12;
    year--;
   } else {
    month--;
   }
   Log.d(tag, "Setting Prev Month in GridCellAdapter: " + "Month: "
     + month + " Year: " + year);
   setGridCellAdapterToDate(month, year);
  }
  if (v == nextMonth) {
   if (month > 11) {
    month = 1;
    year++;
   } else {
    month++;
   }
   Log.d(tag, "Setting Next Month in GridCellAdapter: " + "Month: "
     + month + " Year: " + year);
   setGridCellAdapterToDate(month, year);
  }

 }

 @Override
 public void onDestroy() {
  Log.d(tag, "Destroying View ...");
  super.onDestroy();
 }

 // Inner Class
 public class GridCellAdapter extends BaseAdapter implements OnClickListener {
  private static final String tag = "GridCellAdapter";
  private final Context _context;

  private final List<String> list;
  private static final int DAY_OFFSET = 1;
  private final String[] weekdays = new String[] { "Sun", "Mon", "Tue",
    "Wed", "Thu", "Fri", "Sat" };
  private final String[] months = { "January", "February", "March",
    "April", "May", "June", "July", "August", "September",
    "October", "November", "December" };
  private final int[] daysOfMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30,
    31, 30, 31 };
  private int daysInMonth;
  private int currentDayOfMonth;
  private int currentWeekDay;
  private Button gridcell;
  private TextView num_events_per_day;
  private final HashMap<String, Integer> eventsPerMonthMap;
  private final SimpleDateFormat dateFormatter = new SimpleDateFormat(
    "dd-MMM-yyyy");

  // Days in Current Month
  public GridCellAdapter(Context context, int textViewResourceId,
    int month, int year) {
   super();
   this._context = context;
   this.list = new ArrayList<String>();
   Log.d(tag, "==> Passed in Date FOR Month: " + month + " "
     + "Year: " + year);
   Calendar calendar = Calendar.getInstance();
   setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
   setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));
   Log.d(tag, "New Calendar:= " + calendar.getTime().toString());
   Log.d(tag, "CurrentDayOfWeek :" + getCurrentWeekDay());
   Log.d(tag, "CurrentDayOfMonth :" + getCurrentDayOfMonth());

   // Print Month
   printMonth(month, year);

   // Find Number of Events
   eventsPerMonthMap = findNumberOfEventsPerMonth(year, month);
  }

  private String getMonthAsString(int i) {
   return months[i];
  }

  private String getWeekDayAsString(int i) {
   return weekdays[i];
  }

  private int getNumberOfDaysOfMonth(int i) {
   return daysOfMonth[i];
  }

  public String getItem(int position) {
   return list.get(position);
  }

  @Override
  public int getCount() {
   return list.size();
  }

  /**
   * Prints Month
   * 
   * @param mm
   * @param yy
   */
  private void printMonth(int mm, int yy) {
   Log.d(tag, "==> printMonth: mm: " + mm + " " + "yy: " + yy);
   int trailingSpaces = 0;
   int daysInPrevMonth = 0;
   int prevMonth = 0;
   int prevYear = 0;
   int nextMonth = 0;
   int nextYear = 0;

   int currentMonth = mm - 1;
   String currentMonthName = getMonthAsString(currentMonth);
   daysInMonth = getNumberOfDaysOfMonth(currentMonth);

   Log.d(tag, "Current Month: " + " " + currentMonthName + " having "
     + daysInMonth + " days.");

   GregorianCalendar cal = new GregorianCalendar(yy, currentMonth, 1);
   Log.d(tag, "Gregorian Calendar:= " + cal.getTime().toString());

   if (currentMonth == 11) {
    prevMonth = currentMonth - 1;
    daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
    nextMonth = 0;
    prevYear = yy;
    nextYear = yy + 1;
    Log.d(tag, "*->PrevYear: " + prevYear + " PrevMonth:"
      + prevMonth + " NextMonth: " + nextMonth
      + " NextYear: " + nextYear);
   } else if (currentMonth == 0) {
    prevMonth = 11;
    prevYear = yy - 1;
    nextYear = yy;
    daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
    nextMonth = 1;
    Log.d(tag, "**--> PrevYear: " + prevYear + " PrevMonth:"
      + prevMonth + " NextMonth: " + nextMonth
      + " NextYear: " + nextYear);
   } else {
    prevMonth = currentMonth - 1;
    nextMonth = currentMonth + 1;
    nextYear = yy;
    prevYear = yy;
    daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
    Log.d(tag, "***---> PrevYear: " + prevYear + " PrevMonth:"
      + prevMonth + " NextMonth: " + nextMonth
      + " NextYear: " + nextYear);
   }

   int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
   trailingSpaces = currentWeekDay;

   Log.d(tag, "Week Day:" + currentWeekDay + " is "
     + getWeekDayAsString(currentWeekDay));
   Log.d(tag, "No. Trailing space to Add: " + trailingSpaces);
   Log.d(tag, "No. of Days in Previous Month: " + daysInPrevMonth);

   if (cal.isLeapYear(cal.get(Calendar.YEAR)))
    if (mm == 2)
     ++daysInMonth;
    else if (mm == 3)
     ++daysInPrevMonth;

   // Trailing Month days
   for (int i = 0; i < trailingSpaces; i++) {
    Log.d(tag,
      "PREV MONTH:= "
        + prevMonth
        + " => "
        + getMonthAsString(prevMonth)
        + " "
        + String.valueOf((daysInPrevMonth
          - trailingSpaces + DAY_OFFSET)
          + i));
    list.add(String
      .valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET)
        + i)
      + "-GREY"
      + "-"
      + getMonthAsString(prevMonth)
      + "-"
      + prevYear);
   }

   // Current Month Days
   for (int i = 1; i <= daysInMonth; i++) {
    Log.d(currentMonthName, String.valueOf(i) + " "
      + getMonthAsString(currentMonth) + " " + yy);
    if (i == getCurrentDayOfMonth()) {
     list.add(String.valueOf(i) + "-BLUE" + "-"
       + getMonthAsString(currentMonth) + "-" + yy);
    } else {
     list.add(String.valueOf(i) + "-WHITE" + "-"
       + getMonthAsString(currentMonth) + "-" + yy);
    }
   }

   // Leading Month days
   for (int i = 0; i < list.size() % 7; i++) {
    Log.d(tag, "NEXT MONTH:= " + getMonthAsString(nextMonth));
    list.add(String.valueOf(i + 1) + "-GREY" + "-"
      + getMonthAsString(nextMonth) + "-" + nextYear);
   }
  }

  /**
   * NOTE: YOU NEED TO IMPLEMENT THIS PART Given the YEAR, MONTH, retrieve
   * ALL entries from a SQLite database for that month. Iterate over the
   * List of All entries, and get the dateCreated, which is converted into
   * day.
   * 
   * @param year
   * @param month
   * @return
   */
  private HashMap<String, Integer> findNumberOfEventsPerMonth(int year,
    int month) {
   HashMap<String, Integer> map = new HashMap<String, Integer>();

   return map;
  }

  @Override
  public long getItemId(int position) {
   return position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View row = convertView;
   if (row == null) {
    LayoutInflater inflater = (LayoutInflater) _context
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(R.layout.screen_gridcell, parent, false);
   }

   // Get a reference to the Day gridcell
   gridcell = (Button) row.findViewById(R.id.calendar_day_gridcell);
   gridcell.setOnClickListener(this);

   // ACCOUNT FOR SPACING

   Log.d(tag, "Current Day: " + getCurrentDayOfMonth());
   String[] day_color = list.get(position).split("-");
   String theday = day_color[0];
   String themonth = day_color[2];
   String theyear = day_color[3];
   if ((!eventsPerMonthMap.isEmpty()) && (eventsPerMonthMap != null)) {
    if (eventsPerMonthMap.containsKey(theday)) {
     num_events_per_day = (TextView) row
       .findViewById(R.id.num_events_per_day);
     Integer numEvents = (Integer) eventsPerMonthMap.get(theday);
     num_events_per_day.setText(numEvents.toString());
    }
   }

   // Set the Day GridCell
   gridcell.setText(theday);
   gridcell.setTag(theday + "-" + themonth + "-" + theyear);
   Log.d(tag, "Setting GridCell " + theday + "-" + themonth + "-"
     + theyear);

   if (day_color[1].equals("GREY")) {
    gridcell.setTextColor(getResources()
      .getColor(R.color.lightgray));
   }
   if (day_color[1].equals("WHITE")) {
    gridcell.setTextColor(getResources().getColor(
      R.color.lightgray02));
   }
   if (day_color[1].equals("BLUE")) {
    gridcell.setTextColor(getResources().getColor(R.color.orrange));
   }
   return row;
  }

  @Override
  public void onClick(View view) {
   String date_month_year = (String) view.getTag();
   selectedDayMonthYearButton.setText("Selected: " + date_month_year);
   Log.e("Selected date", date_month_year);
   try {
    Date parsedDate = dateFormatter.parse(date_month_year);
    Log.d(tag, "Parsed Date: " + parsedDate.toString());

   } catch (ParseException e) {
    e.printStackTrace();
   }
  }

  public int getCurrentDayOfMonth() {
   return currentDayOfMonth;
  }

  private void setCurrentDayOfMonth(int currentDayOfMonth) {
   this.currentDayOfMonth = currentDayOfMonth;
  }

  public void setCurrentWeekDay(int currentWeekDay) {
   this.currentWeekDay = currentWeekDay;
  }

  public int getCurrentWeekDay() {
   return currentWeekDay;
  }
 }
}

3-my_calendar_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/lightgray"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/buttonlayout"
        android:layout_width="fill_parent"
        android:layout_height="60sp"
        android:background="@drawable/topbar"
        android:gravity="left|top"
        android:height="60sp"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/settings"
            android:layout_width="54sp"
            android:layout_height="60sp"
            android:background="@drawable/meenu" />

        <ImageView
            android:id="@+id/prevMonth"
            android:layout_width="20sp"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:layout_marginLeft="10sp"
            android:src="@drawable/calendar_left_arrow_selector" >
        </ImageView>

        <TextView
            android:id="@+id/currentMonth"
            android:layout_width="fill_parent"
            android:layout_height="60sp"
            android:layout_weight="0.6"
            android:gravity="center"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="#FFFFFF" >
        </TextView>

        <ImageView
            android:id="@+id/nextMonth"
            android:layout_width="20sp"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:layout_marginRight="10sp"
            android:src="@drawable/calendar_right_arrow_selector" >
        </ImageView>

        <Button
            android:id="@+id/addEvent"
            android:layout_width="54sp"
            android:layout_height="60sp"
            android:background="@drawable/plus" />
    </LinearLayout>

    <Button
        android:id="@+id/selectedDayMonthYear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/calendar_top_header"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#FFFFFF" >
    </Button>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center" >

        <ImageView
            android:id="@+id/calendarheader"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/calendar_days" >
        </ImageView>
    </LinearLayout>

    <GridView
        android:id="@+id/calendar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:numColumns="7" >
    </GridView>

</LinearLayout>

4-screen_gridcell.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/calendar_button_selector"
    android:orientation="vertical" >

    <Button
        android:id="@+id/calendar_day_gridcell"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/calendar_button_selector"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#FFFFFF" >
    </Button>

    <TextView
        android:id="@+id/num_events_per_day"
        style="@style/calendar_event_style"
        android:layout_width="10dip"
        android:layout_height="10dip"
        android:layout_gravity="right" >
    </TextView>

</RelativeLayout>

5-ZIP CODE(Download here!)

Hope it will help you…
Thanks…

Use the Android layer-list to avoid bitmap assets

When you’re working with graphic assets in Android, it’s nearly impossible to avoid importing bitmap files in your project. And that’s ok because for a complicated design (with many shadows and textures for instance) it’s the right solution. Trying to make these graphics work with multiple screens though will eventually get ugly because you’ll have to use 3 or 4 versions for each bitmap. It makes sense then to use any non-bitmap solution where you can. Android’s layer-list is one of these powerful solutions.

What’s the design?

So, trying to have textures and shadows and other simlar cool stuff is impossible without bitmap files (at least I dont know any way to do it), but what about a rectangle with a gradient fill and a line on the top section? Have a look a the following image.

Final result

This could be used as a background for a navigation bar, or a button for example. If you can’t notice the line I’ve mentioned, I’ve zoomed in on the graphic so have another look.

Final result zoomed

Why bother?

Yes it may look tricky to have it working without exporting it as a bitmap and 9-patching it, but it’s actually not so hard. Having an xml based graphic for this kind of background will enable you to switch colors easily anytime you want without exporting a new bitmap from your editor. Obviously, you will not add yet another bitmap in every drawable directory of your project. All you need is one drawable file that can be included in your default drawable directory.

Colors

These are the 3 colors we will need

  1. For the line : #FF7A4D
  2. For the gradient’s start (top) : #8C2300
  3. For the gradient’s end (bottom) : #D34617

In your application you will probably add these as entries in your colors file but this is a quick tip so I’m going to skip this and hardcode them into our drawable.

What is a layer-list anyway?

A layer-list is based on the layers concept of image editors like Photoshop. You add items in the list and they will stay “on top” of each other unless you start defining their offset values to make them align exactly the way you want. The important thing is to remember that your first item (as defined in your xml) will always be the one on the back of all the others and your last item (as defined in your xml) will be the one in front of all the others.

The tricky part here is that you can’t define a line as a layer item. What you also can’t do is set the height for an item. So how can we build this graphic?

Our final result should consist of the gradient and on top of it a line. Unfortunatelly the line is not exactly at the top, it’s drawn with a padding of one pixel from the top so we will need the following shapes

  • One shape to act as the dark line on top
  • One shape to act as the light line right below the dark line
  • One shape to act as the full gradient right below the light line (expanding to the bottom of the graphic)

Since you can’t draw lines or set heights, the two lines will also expand to the bottom of our graphic but only a part of them will be visible because other stuff will be on top of them.

 

The code block above is all you need to make the graphic look like our final result. After you define your root element as a layer-list and add the android namespace, you can start working on the three required items (layers).

The first item acts as our top line and it uses the gradient’s top color.

The second item acts as the second line, it uses the line color and it’s top padding is set to 1dp which means that the shape will start being drawn 1 pixel below the graphic’s top and it will cover the rest of the first item (making the first look line a line).

The third item acts as the gradient, it uses an angle of 270 and the two colors of the gradient. It’s top padding is set to 2dp so it will start being drawn 2 pixels below the graphic’s top and it will cover the rest of the second item (making it also look a line).

Saving this in your drawable directory will make it available to be set as a background in any component you want it.

It may look a hack to use 3 full shapes this way so if you know any other solutions feel free to share them in the comments.