In this tutorial, we will be looking at how to load images from server in to android grid view. Once you complete this tutorial, your application will look like this.
Lets call this application as a Movie Database. This will display list of movies and the name in a grid view.
1 . Creating Database
First of all lets create a database content_db. Create a new file named content_db.sql and copy and paste the below code and save it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
-- phpMyAdmin SQL Dump -- version 4.4.13.1deb1 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: Jun 03, 2016 at 12:31 AM -- Server version: 5.6.30-0ubuntu0.15.10.1 -- PHP Version: 5.6.11-1ubuntu3.2 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Database: `content_db` -- -- -------------------------------------------------------- -- -- Table structure for table `tb_movies` -- CREATE TABLE IF NOT EXISTS `tb_movies` ( `id` int(8) unsigned NOT NULL, `cat_id` int(8) NOT NULL, `title` varchar(100) NOT NULL, `filmname` varchar(100) NOT NULL, `price` decimal(4,2) NOT NULL, `description` text NOT NULL, `poster` varchar(500) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1; -- -- Dumping data for table `tb_movies` -- INSERT INTO `tb_movies` (`id`, `cat_id`, `title`, `filmname`, `price`, `description`, `poster`) VALUES (1, 1, 'Age of Ultron', 'Avengers', 25.00, 'Marvel Studios presents “Avengers: Age of Ultron,” the epic follow-up to the biggest Super Hero movie of all time. When Tony Stark tries to jumpstart a dormant peacekeeping program, things go awry and Earth’s Mightiest Heroes, including Iron Man, Captain America, Thor, The Incredible Hulk, Black Widow and Hawkeye, are put to the ultimate test as the fate of the planet hangs in the balance. As the villainous Ultron emerges, it is up to The Avengers to stop him from enacting his terrible plans, and soon uneasy alliances and unexpected action pave the way for an epic and unique global adventure.', 'http://cdn.movieweb.com/img.teasers.posters/FI93cxJOB7Xlcf_246_b.jpg'), (2, 1, 'Ant-Man', 'Ant-Man', 12.60, 'From director Joe Wright comes “Pan,” a live-action feature presenting a wholly original adventure about the beginnings of the beloved characters created by J.M. Barrie.Peter (Levi Miller) is a mischievous 12-year-old boy with an irrepressible rebellious streak, but in the bleak London orphanage where he has lived his whole life those qualities do not exactly fly. Then one incredible night, Peter is whisked away from the orphanage and spirited off to a fantastical world of pirates, warriors and fairies called Neverland. There, he finds amazing adventures and fights life-or-death battles while trying to uncover the secret of his mother, who left him at the orphanage so long ago, and his rightful place in this magical land.', 'http://cdn.movieweb.com/img.teasers.posters/FIgMVXPFBv0ykl_250_a.jpg'), (3, 1, 'Fury Road', 'Mad Max', 56.52, 'From director George Miller, originator of the post-apocalyptic genre and mastermind behind the legendary “Mad Max” franchise, comes “Mad Max: Fury Road,” a return to the world of the Road Warrior, Max Rockatansky. Haunted by his turbulent past, Mad Max (Tom Hardy) believes the best way to survive is to wander alone. Nevertheless, he becomes swept up with a group fleeing across the Wasteland in a War Rig driven by an elite Imperator, Furiosa (Charlize Theron). They are escaping a Citadel tyrannized by the Immortan Joe (Hugh Keays-Byrne), from whom something irreplaceable has been taken. Enraged, the Warlord marshals all his gangs and pursues the rebels ruthlessly in the high-octane Road War that follows.', 'http://cdn.movieweb.com/img.teasers.posters/FINxHUQTlQcCRW_245_a.jpg'), (4, 1, 'Jurassic World', 'Jurassic World', 42.30, 'Twenty-two years after the events of Jurassic Park, Isla Nublar now features a fully functioning dinosaur theme park, Jurassic World, as originally envisioned by John Hammond. After 10 years of operation and visitor rates declining, in order to fulfill a corporate mandate, a new attraction is created to re-spark visitor''s interest, which backfires horribly.', 'http://cdn.movieweb.com/img.teasers.posters/FIcl6jegGeDJfd_253_a.jpg'), (5, 2, 'The Nice Guys', 'The Nice Guys', 85.36, 'A mismatched pair of private eyes investigate the apparent suicide of a fading porn star in 1970s Los Angeles.', 'http://ia.media-imdb.com/images/M/MV5BMjcwNDA5MDYyNl5BMl5BanBnXkFtZTgwNjg0NDkzNzE@._V1_UX182_CR0,0,182,268_AL_.jpg'), (6, 2, 'Sorority Rising', 'Neighbors 2', 35.75, 'When their new next-door neighbors turn out to be a sorority even more debaucherous than the fraternity previously living there, Mac and Kelly team with their former enemy, Teddy, to bring the girls down.When their new next-door neighbors turn out to be a sorority even more debaucherous than the fraternity previously living there, Mac and Kelly team with their former enemy, Teddy, to bring the girls down.', 'http://ia.media-imdb.com/images/M/MV5BMTY0NzUxMDUzN15BMl5BanBnXkFtZTgwNzI2MTY4ODE@._V1_UX182_CR0,0,182,268_AL_.jpg'), (7, 2, '\r\nDeadpool', '\r\nDeadpool', 72.38, 'A former Special Forces operative turned mercenary is subjected to a rogue experiment that leaves him with accelerated healing powers, adopting the alter ego Deadpool.', 'http://ia.media-imdb.com/images/M/MV5BMjQyODg5Njc4N15BMl5BanBnXkFtZTgwMzExMjE3NzE@._V1_UY268_CR1,0,182,268_AL_.jpg'); -- -------------------------------------------------------- -- -- Table structure for table `tb_movies_cat` -- CREATE TABLE IF NOT EXISTS `tb_movies_cat` ( `id` int(10) unsigned NOT NULL, `name` varchar(100) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; -- -- Dumping data for table `tb_movies_cat` -- INSERT INTO `tb_movies_cat` (`id`, `name`) VALUES (1, 'Action'), (2, 'Comedy'); -- -- Indexes for dumped tables -- -- -- Indexes for table `tb_movies` -- ALTER TABLE `tb_movies` ADD PRIMARY KEY (`id`); -- -- Indexes for table `tb_movies_cat` -- ALTER TABLE `tb_movies_cat` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `tb_movies` -- ALTER TABLE `tb_movies` MODIFY `id` int(8) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=8; -- -- AUTO_INCREMENT for table `tb_movies_cat` -- ALTER TABLE `tb_movies_cat` MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=3; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; |
Now import the this file in to the database you have created.
2. Creating an API
Now you have the database ready, lets create an API to get all movies using PHP.
Copy the below code and save it in to file named content_db_getAllMovies.php in localhost location ( in my case its /var/www/html/). you can save it in your localhost location.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?php class Movies{ public function getallmovies(){ $db = new Db(); $results = $db->getmovies(); echo json_encode($results); } } class Db { public $connection; private $servername = "localhost"; private $username = "root"; private $password = "sathyabaman"; private $database = "content_db"; public function connect(){ try { $this->connection = new PDO("mysql:host={$this->servername};dbname={$this->database}", $this->username, $this->password); // set the PDO error mode to exception $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //$this->logger->writeLog('MySQL Connection Success'); return $this->connection; } catch(PDOException $e) { $this->logger->writeLog('MySQL Connection failed'); return false; } } public function getmovies(){ $this->connect(); $query = "SELECT id, title AS name, poster AS image FROM tb_movies"; $stmt = $this->connection->prepare($query); $result = $stmt->execute(); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); return $results; } } $movies = new Movies(); $movies->getallmovies(); |
Make sure to change your database configuration as per your database credentials, In the above file.
1 2 3 4 |
private $servername = "localhost"; private $username = "root"; private $password = "sathyabaman"; private $database = "content_db"; |
3. Creating an Android application
Now lets create a new android application called MovieDatabase, when you create an new application in android studio it will automatically create a new activity called MainActivity. You can change it to anything you want, but i recommend to leave it as it is for this tutorial.
4. Creating Styles and Drawable
Copy and paste the below code inside /res/values/colors.xml file.
1 2 3 4 5 6 7 8 |
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorClear">#FFFF</color> </resources> |
save and close it.
Now create a new file called grid_color_selector.xml inside /res/drawable/ folder and then copy and paste the below code.
1 2 3 4 5 6 7 8 |
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorPrimary" android:state_pressed="true" /> <item android:drawable="@color/colorPrimary" android:state_selected="true" /> <item android:drawable="@color/colorClear" /> </selector> |
save and close it.
5. Creating Layout files
Now create a new file called grid_item_layout.xml in your /res/layout/ folder and copy and paste the below code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:background="@drawable/grid_color_selector" android:orientation="vertical" android:padding="5dp"> <ImageView android:id="@+id/grid_item_image" android:layout_width="100dp" android:scaleType="fitCenter" android:layout_height="100dp" /> <TextView android:id="@+id/grid_item_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:ellipsize="marquee" android:gravity="center" android:maxLines="2" android:textSize="12sp" /> </LinearLayout> |
save and close it.
Now open your activity_main.xml which is located in /res/layout/ folder. open the file and copy and paste the below code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f0f0f0"> <GridView android:id="@+id/gridView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:columnWidth="100dp" android:drawSelectorOnTop="true" android:gravity="center" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:verticalSpacing="5dp" android:focusable="true" android:clickable="true"/> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/progressBar" android:layout_centerInParent="true" android:visibility="gone"/> </RelativeLayout> |
Save and close it.
6. Java classes
create a new java file named GridViewAdapter.java inside your package and copy and paste the below code. make sure to change your package name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
package baman.lankahomes.lk.moviedatabase; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; /** * Created by baman on 6/2/16. */ public class GridViewAdapter extends ArrayAdapter<GridItem> { //private final ColorMatrixColorFilter grayscaleFilter; private Context mContext; private int layoutResourceId; private ArrayList<GridItem> mGridData = new ArrayList<GridItem>(); public GridViewAdapter(Context mContext, int layoutResourceId, ArrayList<GridItem> mGridData) { super(mContext, layoutResourceId, mGridData); this.layoutResourceId = layoutResourceId; this.mContext = mContext; this.mGridData = mGridData; } /** * Updates grid data and refresh grid items. * * @param mGridData */ public void setGridData(ArrayList<GridItem> mGridData) { this.mGridData = mGridData; notifyDataSetChanged(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; ViewHolder holder; if (row == null) { LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); holder = new ViewHolder(); holder.titleTextView = (TextView) row.findViewById(R.id.grid_item_title); holder.imageView = (ImageView) row.findViewById(R.id.grid_item_image); row.setTag(holder); } else { holder = (ViewHolder) row.getTag(); } GridItem item = mGridData.get(position); holder.titleTextView.setText(Html.fromHtml(item.getTitle())); Picasso.with(mContext).load(item.getImage()).into(holder.imageView); return row; } static class ViewHolder { TextView titleTextView; ImageView imageView; } } |
save and close it.
Now create another new file called GridItem.java inside your package and then copy and paste the below code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package baman.lankahomes.lk.moviedatabase; /** * Created by baman on 6/2/16. */ public class GridItem { private String id; private String image; private String title; public GridItem() { super(); } public void setId(String id){ this.id = id; } public String getId(){ return id; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } |
save and close it.
Now open you MainActivity.java class and make sure it looks like the below code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
package baman.lankahomes.lk.moviedatabase; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private GridView mGridView; private ProgressBar mProgressBar; private GridViewAdapter mGridAdapter; private ArrayList<GridItem> mGridData; private String FEED_URL = "http://localhost/content_db_getAllMovies.php"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGridView = (GridView) findViewById(R.id.gridView); mProgressBar = (ProgressBar) findViewById(R.id.progressBar); //Initialize with empty data mGridData = new ArrayList<>(); mGridAdapter = new GridViewAdapter(this, R.layout.grid_item_layout, mGridData); mGridView.setAdapter(mGridAdapter); //Grid view click event mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { //Get item at position GridItem item = (GridItem) parent.getItemAtPosition(position); Intent intent = new Intent(MainActivity.this, DetailsActivity.class); //Pass the image title and url to DetailsActivity intent. putExtra("id", item.getId()). putExtra("title", item.getTitle()). putExtra("image", item.getImage()); //Start details activity startActivity(intent); } }); //Start download new AsyncHttpTask().execute(FEED_URL); mProgressBar.setVisibility(View.VISIBLE); } //Downloading data asynchronously public class AsyncHttpTask extends AsyncTask<String, Void, Integer> { @Override protected Integer doInBackground(String... params) { Integer result = 0; try { // Create Apache HttpClient HttpClient httpclient = new DefaultHttpClient(); HttpResponse httpResponse = httpclient.execute(new HttpGet(params[0])); int statusCode = httpResponse.getStatusLine().getStatusCode(); // 200 represents HTTP OK if (statusCode == 200) { String response = streamToString(httpResponse.getEntity().getContent()); parseResult(response); result = 1; // Successful } else { result = 0; //"Failed } } catch (Exception e) { Log.d(TAG, e.getLocalizedMessage()); } return result; } @Override protected void onPostExecute(Integer result) { // Download complete. Lets update UI if (result == 1) { mGridAdapter.setGridData(mGridData); } else { Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show(); } //Hide progressbar mProgressBar.setVisibility(View.GONE); } } String streamToString(InputStream stream) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream)); String line; String result = ""; while ((line = bufferedReader.readLine()) != null) { result += line; } // Close stream if (null != stream) { stream.close(); } return result; } /** * Parsing the feed results and get the list * * @param result */ private void parseResult(String result) { try { JSONArray mJsonArray = new JSONArray(result); JSONObject mJsonObject = new JSONObject(); GridItem item; for (int i = 0; i < mJsonArray.length(); i++) { item = new GridItem(); mJsonObject = mJsonArray.getJSONObject(i); String id = mJsonObject.getString("id"); String name = mJsonObject.getString("name"); String image = mJsonObject.getString("image"); item.setId(id); item.setTitle(name); if(image !=null) item.setImage(image); mGridData.add(item); } } catch (JSONException e) { e.printStackTrace(); } } } |
save and close it.
7. Create a second activity
Now we need to create a new activity to be viewed when ever the movie is clicked. So lets create a new activity called DetailsActivity using your android studio.
8. Modify Manifest file.
This application need a internet connection to get data from the server, therefore it is necessary to add that permission to the manifest file. As shown in the below code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="baman.lankahomes.lk.moviedatabase"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".DetailsActivity" android:label="@string/details"></activity> </application> </manifest> |
9. Gradle Build
It is important to tell the gradle how to build the application. Note this application is using HttpClient package which is no more supported in android studio. Therefore its is very important how you set the build.gradle file.
Make sure your build.gradle file looks exactly as shown in the below code snippet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.2" useLibrary 'org.apache.http.legacy' defaultConfig { applicationId "baman.lankahomes.lk.moviedatabase" minSdkVersion 8 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' testCompile 'junit:junit:4.12' compile 'com.squareup.picasso:picasso:2.5.2' } |
make sure to set your applicationId. That’s it. compile the application and run it on your device or emulator. It should work fine.
10. Happy coding.
Feel free to tell me your comments and feedback’s below in the comments section. Thank you. 🙂