In the 1st Part we prepared required classes for this app. In this we’ll start adding one by one screen to the app and at the end of the article we should be able to complete the application.

android-free-wallpapers-app-banner-2

Styling The Action Bar

12. You might noticed that this app action bar is having customized background color. That can be done by defining a custom theme in res ⇒ values ⇒ styles.xml folder. Also this is not a complete action bar customization. I am just changing the background color of it.

If you want to customize it completely, Styling the Action Bar will helps you. Add below code in res ⇒ values ⇒ styles.xml. If you don’t find styles.xml, create a new file in values folder.

<resources>

    <style name="FreeWallTheme" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarStyle">@style/MyActionBarTheme</item>
        <item name="android:actionOverflowButtonStyle">@style/OverFlow</item>
    </style>

    <style name="MyActionBarTheme" parent="@android:style/Widget.Holo.Light.ActionBar">
        <item name="android:background">@color/action_bar</item>
        <item name="android:titleTextStyle">@style/TitleTextStyle</item>
    </style>

    <style name="TitleTextStyle" parent="android:TextAppearance.Holo.Widget.ActionBar.Title">
        <item name="android:textColor">@color/action_bar_title</item>
    </style>

    <style name="OverFlow" parent="android:style/Widget.Holo.ActionButton.Overflow">
        <item name="android:src">@drawable/ic_action_overflow</item>
    </style>

</resources>

13. Now in order to apply this style, open the AndroidManifest.xml file and add the style using android:theme attribute for tag. Also add below permissions too.

INTERNET – To consume internet
WRITE_EXTERNAL_STORAGE – To store wallpapers in SDCard
SET_WALLPAPER – To update the device wallpaper

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.awesomewallpapers"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />

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

    <application
        android:name="info.androidhive.awesomewallpapers.app.AppController"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/FreeWallTheme" >
        <!-- all the activities goes here -->
    </application>

</manifest>

Now if you run the app, you should see the action bar color changed.

Adding the Splash Screen

Splash screens are not necessary for every app. But for our app it make sense to have a splash screen as we have to download wallpapers categories before going into the app. In brief we make a request to Picasa to get list of public albums (in our case those are wallpapers categories) and store them in shared preferences. So let’s create the necessary files for the splash screen.

14. Create an xml file named activity_splash.xml under res ⇒ layout folder.

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

    <ImageView android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/splash_screen"
        android:scaleType="centerCrop"/>
    

</LinearLayout>
android freewallpapers app splash screen

15. Now create a class named SplashActivity.java in the app main package and paste the below code. Here we are making a json call to Picasa and fetching list of albums. Once albums are fetched we are storing them in Shared Preferences. Later these categories will be loaded into navigation drawer.

package info.androidhive.awesomewallpapers;

import info.androidhive.awesomewallpapers.app.AppConst;
import info.androidhive.awesomewallpapers.app.AppController;
import info.androidhive.awesomewallpapers.picasa.model.Category;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;

public class SplashActivity extends Activity {
	private static final String TAG = SplashActivity.class.getSimpleName();
	private static final String TAG_FEED = "feed", TAG_ENTRY = "entry",
			TAG_GPHOTO_ID = "gphoto$id", TAG_T = "$t",
			TAG_ALBUM_TITLE = "title";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
		getActionBar().hide();
		setContentView(R.layout.activity_splash);

		// Picasa request to get list of albums
		String url = AppConst.URL_PICASA_ALBUMS
				.replace("_PICASA_USER_", AppController.getInstance()
						.getPrefManger().getGoogleUserName());
		
		Log.d(TAG, "Albums request url: " + url);

		// Preparing volley's json object request
		JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET, url,
				null, new Response.Listener<JSONObject>() {

					@Override
					public void onResponse(JSONObject response) {
						Log.d(TAG, "Albums Response: " + response.toString());
						List<Category> albums = new ArrayList<Category>();
						try {
							// Parsing the json response
							JSONArray entry = response.getJSONObject(TAG_FEED)
									.getJSONArray(TAG_ENTRY);

							// loop through albums nodes and add them to album
							// list
							for (int i = 0; i < entry.length(); i++) {
								JSONObject albumObj = (JSONObject) entry.get(i);
								// album id
								String albumId = albumObj.getJSONObject(
										TAG_GPHOTO_ID).getString(TAG_T);

								// album title
								String albumTitle = albumObj.getJSONObject(
										TAG_ALBUM_TITLE).getString(TAG_T);

								Category album = new Category();
								album.setId(albumId);
								album.setTitle(albumTitle);

								// add album to list
								albums.add(album);

								Log.d(TAG, "Album Id: " + albumId
										+ ", Album Title: " + albumTitle);
							}

							// Store albums in shared pref
							AppController.getInstance().getPrefManger()
									.storeCategories(albums);

							// String the main activity
							Intent intent = new Intent(getApplicationContext(),
									MainActivity.class);
							startActivity(intent);
							// closing spalsh activity
							finish();

						} catch (JSONException e) {
							e.printStackTrace();
							Toast.makeText(getApplicationContext(),
									getString(R.string.msg_unknown_error),
									Toast.LENGTH_LONG).show();
						}

					}
				}, new Response.ErrorListener() {

					@Override
					public void onErrorResponse(VolleyError error) {
						Log.e(TAG, "Volley Error: " + error.getMessage());

						// show error toast
						Toast.makeText(getApplicationContext(),
								getString(R.string.splash_error),
								Toast.LENGTH_LONG).show();

						// Unable to fetch albums
						// check for existing Albums data in Shared Preferences
						if (AppController.getInstance().getPrefManger()
								.getCategories() != null && AppController.getInstance().getPrefManger()
								.getCategories().size() > 0) {
							// String the main activity
							Intent intent = new Intent(getApplicationContext(),
									MainActivity.class);
							startActivity(intent);
							// closing spalsh activity
							finish();
						} else {
							// Albums data not present in the shared preferences
							// Launch settings activity, so that user can modify
							// the settings

							Intent i = new Intent(SplashActivity.this,
									SettingsActivity.class);
							// clear all the activities
							i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
									| Intent.FLAG_ACTIVITY_CLEAR_TASK);
							startActivity(i);
						}

					}
				});

		// disable the cache for this request, so that it always fetches updated
		// json
		jsonObjReq.setShouldCache(false);

		// Making the request
		AppController.getInstance().addToRequestQueue(jsonObjReq);

	}

}

16. Now add the SplashActivity as launcher activity in the AndroidManifest.xml inside <application>

   <application ....>
        <activity
            android:name="info.androidhive.awesomewallpapers.SplashActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

Now if you run the app, you should see albums json logged in LogCat. If yes, we can move to the next step i.e adding navigation drawer and displaying the wallpaper categories.

Adding Navigation Drawer

Before following this step make sure that you read Android Sliding Menu using Navigation Drawer tutorial to make this step simple for you. To add navigation drawer, we need to create fewer layouts and classes.

17. Create drawer_list_item.xml under res ⇒ layout directory. This is the layout file for navigation drawer list item to display wallpaper category name.

<?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="48dp" 
    android:background="@drawable/list_selector">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"        
        android:minHeight="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:textColor="@color/list_item_title"
        android:gravity="center_vertical"
        android:paddingRight="10dp"
        android:paddingLeft="10dp"/>

</RelativeLayout>

18. Create NavDrawerItem.java in your project’s main package and paste the below code. This is a model class for navigation list item.

19. Now we need to create the custom list adapter class which provides data to navigation list view. Create a class named NavDrawerListAdapter.java under adapter package. This adapter class inflates the drawer_list_item.xml layout by displaying appropriate wallpaper category name.

20. Now we need to create a list view element in our main activity. Create an xml named activity_main.xml with the below content.

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Framelayout to display Fragments -->
    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Listview to display slider menu -->
    <ListView
        android:id="@+id/list_slidermenu"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@color/list_divider"
        android:dividerHeight="1dp"        
        android:listSelector="@drawable/list_selector"
        android:background="@color/list_background"/>
</android.support.v4.widget.DrawerLayout>

21. Open your main activity class (in my case MainActivity.java) and add the below code. Eclipse might show you errors on the lines where you see GridFragment. For now comment those lines.

package info.androidhive.awesomewallpapers;

import info.androidhive.awesomewallpapers.app.AppController;
import info.androidhive.awesomewallpapers.helper.NavDrawerListAdapter;
import info.androidhive.awesomewallpapers.picasa.model.Category;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	private DrawerLayout mDrawerLayout;
	private ListView mDrawerList;
	private ActionBarDrawerToggle mDrawerToggle;

	// Navigation drawer title
	private CharSequence mDrawerTitle;
	private CharSequence mTitle;
	private List<Category> albumsList;
	private ArrayList<NavDrawerItem> navDrawerItems;
	private NavDrawerListAdapter adapter;

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

		mTitle = mDrawerTitle = getTitle();

		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		mDrawerList = (ListView) findViewById(R.id.list_slidermenu);

		navDrawerItems = new ArrayList<NavDrawerItem>();

		// Getting the albums from shared preferences
		albumsList = AppController.getInstance().getPrefManger().getCategories();

		// Insert "Recently Added" in navigation drawer first position
		Category recentAlbum = new Category(null,
				getString(R.string.nav_drawer_recently_added));

		albumsList.add(0, recentAlbum);

		// Loop through albums in add them to navigation drawer adapter
		for (Category a : albumsList) {
			navDrawerItems.add(new NavDrawerItem(a.getId(), a.getTitle()));
		}

		mDrawerList.setOnItemClickListener(new SlideMenuClickListener());

		// Setting the nav drawer list adapter
		adapter = new NavDrawerListAdapter(getApplicationContext(),
				navDrawerItems);
		mDrawerList.setAdapter(adapter);

		// Enabling action bar app icon and behaving it as toggle button
		getActionBar().setDisplayHomeAsUpEnabled(true);
		getActionBar().setHomeButtonEnabled(true);
		getActionBar().setIcon(
				new ColorDrawable(getResources().getColor(
						android.R.color.transparent)));

		mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
				R.drawable.ic_drawer, R.string.app_name, R.string.app_name) {
			public void onDrawerClosed(View view) {
				getActionBar().setTitle(mTitle);
				// calling onPrepareOptionsMenu() to show action bar icons
				invalidateOptionsMenu();
			}

			public void onDrawerOpened(View drawerView) {
				getActionBar().setTitle(mDrawerTitle);
				// calling onPrepareOptionsMenu() to hide action bar icons
				invalidateOptionsMenu();
			}
		};
		mDrawerLayout.setDrawerListener(mDrawerToggle);

		if (savedInstanceState == null) {
			// on first time display view for first nav item
			displayView(0);
		}
	}

	/**
	 * Navigation drawer menu item click listener
	 * */
	private class SlideMenuClickListener implements
			ListView.OnItemClickListener {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			// display view for selected nav drawer item
			displayView(position);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	/**
	 * On menu item selected
	 * */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// toggle nav drawer on selecting action bar app icon/title
		if (mDrawerToggle.onOptionsItemSelected(item)) {
			return true;
		}
		// Handle action bar actions click
		switch (item.getItemId()) {
		case R.id.action_settings:
			// Selected settings menu item
			// launch Settings activity
			Intent intent = new Intent(MainActivity.this,
					SettingsActivity.class);
			startActivity(intent);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	/**
	 * Called when invalidateOptionsMenu() is triggered
	 */
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		// if nav drawer is opened, hide the action items
		boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
		menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
		return super.onPrepareOptionsMenu(menu);
	}

	/**
	 * Diplaying fragment view for selected nav drawer list item
	 * */
	private void displayView(int position) {
		// update the main content by replacing fragments
		Fragment fragment = null;
		switch (position) {
		case 0:
			// Recently added item selected
			// don't pass album id to grid fragment
			fragment = GridFragment.newInstance(null);
			break;

		default:
			// selected wallpaper category
			// send album id to grid fragment to list all the wallpapers
			String albumId = albumsList.get(position).getId();
			fragment = GridFragment.newInstance(albumId);
			break;
		}

		if (fragment != null) {
			FragmentManager fragmentManager = getFragmentManager();
			fragmentManager.beginTransaction()
					.replace(R.id.frame_container, fragment).commit();

			// update selected item and title, then close the drawer
			mDrawerList.setItemChecked(position, true);
			mDrawerList.setSelection(position);
			setTitle(albumsList.get(position).getTitle());
			mDrawerLayout.closeDrawer(mDrawerList);
		} else {
			// error in creating fragment
			Log.e(TAG, "Error in creating fragment");
		}
	}

	@Override
	public void setTitle(CharSequence title) {
		mTitle = title;
		getActionBar().setTitle(mTitle);
	}

	/**
	 * When using the ActionBarDrawerToggle, you must call it during
	 * onPostCreate() and onConfigurationChanged()...
	 */

	@Override
	protected void onPostCreate(Bundle savedInstanceState) {
		super.onPostCreate(savedInstanceState);
		// Sync the toggle state after onRestoreInstanceState has occurred.
		mDrawerToggle.syncState();
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		// Pass any configuration change to the drawer toggls
		mDrawerToggle.onConfigurationChanged(newConfig);
	}
}

22. Add the MainActivity.java activity in the AndroidManifest.xml inside <application> tag.

<application ...>
        <activity
            android:name="info.androidhive.awesomewallpapers.MainActivity"
            android:screenOrientation="portrait" >
        </activity>
</application>

Now run the app and test it once. You should see the wallpaper categories displayed in navigation drawer.

android free wallpapers app navigation drawer

Wallpapers Grid Thumbnail Preview

The next step is displaying the wallpapers of selected category in a thumbnail fashion. For this we need a GridView and few other class files.

23. Create an xml file named grid_item_photo.xml under res ⇒ layout and add the below code. This layout defines single grid item tile in the GridView. Here we are using volley’s NetworkImageView to download the image from an URL and display.

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

    <ImageView
        android:id="@+id/imgLoader"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerInParent="true"
        android:src="@drawable/ico_loader" />

    <!-- Thumbnail Image -->

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/thumbnail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>

24. Create another layout file named fragment_grid.xml under res ⇒ layout folder. This layout contains actual GridView and a ProgressBar to show to loading progress while the request is in process.

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

    <ProgressBar
        android:id="@+id/pbLoader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" 
        style="?android:attr/progressBarStyle">
    </ProgressBar>

    <GridView
        android:id="@+id/grid_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/grid_bg"
        android:gravity="center"
        android:numColumns="auto_fit"
        android:stretchMode="columnWidth">
    </GridView>

</RelativeLayout>

25. Now just like navigation drawer adapter, we need to create another adapter class to provide data to GridView. So create a class named GridViewAdapter.java under adapter package. This class inflates grid_item_photo.xml layout with appropriate wallpaper image.

package info.androidhive.awesomewallpapers.helper;

import info.androidhive.awesomewallpapers.R;
import info.androidhive.awesomewallpapers.app.AppController;
import info.androidhive.awesomewallpapers.picasa.model.Wallpaper;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

public class GridViewAdapter extends BaseAdapter {

	private Activity _activity;
	private LayoutInflater inflater;
	private List<Wallpaper> wallpapersList = new ArrayList<Wallpaper>();
	private int imageWidth;
	ImageLoader imageLoader = AppController.getInstance().getImageLoader();

	public GridViewAdapter(Activity activity, List<Wallpaper> wallpapersList,
			int imageWidth) {
		this._activity = activity;
		this.wallpapersList = wallpapersList;
		this.imageWidth = imageWidth;
	}

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

	@Override
	public Object getItem(int position) {
		return this.wallpapersList.get(position);
	}

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

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (inflater == null)
			inflater = (LayoutInflater) _activity
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		if (convertView == null)
			convertView = inflater.inflate(R.layout.grid_item_photo, null);

		if (imageLoader == null)
			imageLoader = AppController.getInstance().getImageLoader();

		// Grid thumbnail image view
		NetworkImageView thumbNail = (NetworkImageView) convertView
				.findViewById(R.id.thumbnail);

		Wallpaper p = wallpapersList.get(position);

		thumbNail.setScaleType(ImageView.ScaleType.CENTER_CROP);
		thumbNail.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth,
				imageWidth));
		thumbNail.setImageUrl(p.getUrl(), imageLoader);

		return convertView;
	}

}

26. Create a class named GridFragment.java under the project’s main package. This is where we implement actual GridView implementation. This is main fragment class will be loaded when an item from navigation drawer selected. Briefly it works as below

> User selects a wallpaper category from navigation drawer.
> The selected category id (in other words album id) will be passed to GridFragment
> Using the category id, we make another request to Picasa to get all the photos under that category.
> Finally the photos json will be parsed and wallpaper model objects will be passed to GridViewAdpater to render the wallpapers in grid view.

package info.androidhive.awesomewallpapers;

import info.androidhive.awesomewallpapers.app.AppConst;
import info.androidhive.awesomewallpapers.app.AppController;
import info.androidhive.awesomewallpapers.helper.GridViewAdapter;
import info.androidhive.awesomewallpapers.picasa.model.Wallpaper;
import info.androidhive.awesomewallpapers.util.PrefManager;
import info.androidhive.awesomewallpapers.util.Utils;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Fragment;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;

public class GridFragment extends Fragment {
	private static final String TAG = GridFragment.class.getSimpleName();
	private Utils utils;
	private GridViewAdapter adapter;
	private GridView gridView;
	private int columnWidth;
	private static final String bundleAlbumId = "albumId";
	private String selectedAlbumId;
	private List<Wallpaper> photosList;
	private ProgressBar pbLoader;
	private PrefManager pref;

	// Picasa JSON response node keys
	private static final String TAG_FEED = "feed", TAG_ENTRY = "entry",
			TAG_MEDIA_GROUP = "media$group",
			TAG_MEDIA_CONTENT = "media$content", TAG_IMG_URL = "url",
			TAG_IMG_WIDTH = "width", TAG_IMG_HEIGHT = "height", TAG_ID = "id",
			TAG_T = "$t";

	public GridFragment() {
	}

	public static GridFragment newInstance(String albumId) {
		GridFragment f = new GridFragment();
		Bundle args = new Bundle();
		args.putString(bundleAlbumId, albumId);
		f.setArguments(args);
		return f;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		photosList = new ArrayList<Wallpaper>();
		pref = new PrefManager(getActivity());

		// Getting Album Id of the item selected in navigation drawer
		// if Album Id is null, user is selected recently added option
		if (getArguments().getString(bundleAlbumId) != null) {
			selectedAlbumId = getArguments().getString(bundleAlbumId);
			Log.d(TAG,
					"Selected album id: "
							+ getArguments().getString(bundleAlbumId));
		} else {
			Log.d(TAG, "Selected recentlyed added album");
			selectedAlbumId = null;
		}

		// Preparing the request url
		String url = null;
		if (selectedAlbumId == null) {
			// Recently added album url
			url = AppConst.URL_RECENTLY_ADDED.replace("_PICASA_USER_",
					pref.getGoogleUserName());
		} else {
			// Selected an album, replace the Album Id in the url
			url = AppConst.URL_ALBUM_PHOTOS.replace("_PICASA_USER_",
					pref.getGoogleUserName()).replace("_ALBUM_ID_",
					selectedAlbumId);
		}

		Log.d(TAG, "Final request url: " + url);

		View rootView = inflater.inflate(R.layout.fragment_grid, container,
				false);

		// Hiding the gridview and showing loader image before making the http
		// request
		gridView = (GridView) rootView.findViewById(R.id.grid_view);
		gridView.setVisibility(View.GONE);
		pbLoader = (ProgressBar) rootView.findViewById(R.id.pbLoader);
		pbLoader.setVisibility(View.VISIBLE);

		utils = new Utils(getActivity());

		/**
		 * Making volley's json object request to fetch list of photos of an
		 * album
		 * */
		JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET, url,
				null, new Response.Listener<JSONObject>() {

					@Override
					public void onResponse(JSONObject response) {
						Log.d(TAG,
								"List of photos json reponse: "
										+ response.toString());
						try {
							// Parsing the json response
							JSONArray entry = response.getJSONObject(TAG_FEED)
									.getJSONArray(TAG_ENTRY);

							// looping through each photo and adding it to list
							// data set
							for (int i = 0; i < entry.length(); i++) {
								JSONObject photoObj = (JSONObject) entry.get(i);
								JSONArray mediacontentArry = photoObj
										.getJSONObject(TAG_MEDIA_GROUP)
										.getJSONArray(TAG_MEDIA_CONTENT);

								if (mediacontentArry.length() > 0) {
									JSONObject mediaObj = (JSONObject) mediacontentArry
											.get(0);

									String url = mediaObj
											.getString(TAG_IMG_URL);

									String photoJson = photoObj.getJSONObject(
											TAG_ID).getString(TAG_T)
											+ "&imgmax=d";									

									int width = mediaObj.getInt(TAG_IMG_WIDTH);
									int height = mediaObj
											.getInt(TAG_IMG_HEIGHT);

									Wallpaper p = new Wallpaper(photoJson, url, width,
											height);

									// Adding the photo to list data set
									photosList.add(p);

									Log.d(TAG, "Photo: " + url + ", w: "
											+ width + ", h: " + height);
								}
							}

							// Notify list adapter about dataset changes. So
							// that it renders grid again
							adapter.notifyDataSetChanged();

							// Hide the loader, make grid visible
							pbLoader.setVisibility(View.GONE);
							gridView.setVisibility(View.VISIBLE);

						} catch (JSONException e) {
							e.printStackTrace();
							Toast.makeText(getActivity(),
									getString(R.string.msg_unknown_error),
									Toast.LENGTH_LONG).show();
						}

					}
				}, new Response.ErrorListener() {

					@Override
					public void onErrorResponse(VolleyError error) {
						Log.e(TAG, "Error: " + error.getMessage());
						// unable to fetch wallpapers
						// either google username is wrong or
						// devices doesn't have internet connection
						Toast.makeText(getActivity(),
								getString(R.string.msg_wall_fetch_error),
								Toast.LENGTH_LONG).show();

					}
				});

		// Remove the url from cache
		AppController.getInstance().getRequestQueue().getCache().remove(url);

		// Disable the cache for this url, so that it always fetches updated
		// json
		jsonObjReq.setShouldCache(false);

		// Adding request to request queue
		AppController.getInstance().addToRequestQueue(jsonObjReq);

		// Initilizing Grid View
		InitilizeGridLayout();

		// Gridview adapter
		adapter = new GridViewAdapter(getActivity(), photosList, columnWidth);

		// setting grid view adapter
		gridView.setAdapter(adapter);

		// Grid item select listener
		gridView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View v,
					int position, long id) {

				// On selecting the grid image, we launch fullscreen activity
				Intent i = new Intent(getActivity(),
						FullScreenViewActivity.class);

				// Passing selected image to fullscreen activity
				Wallpaper photo = photosList.get(position);

				i.putExtra(FullScreenViewActivity.TAG_SEL_IMAGE, photo);
				startActivity(i);
			}
		});

		return rootView;
	}

	/**
	 * Method to calculate the grid dimensions Calculates number columns and
	 * columns width in grid
	 * */
	private void InitilizeGridLayout() {
		Resources r = getResources();
		float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				AppConst.GRID_PADDING, r.getDisplayMetrics());

		// Column width
		columnWidth = (int) ((utils.getScreenWidth() - ((pref
				.getNoOfGridColumns() + 1) * padding)) / pref
				.getNoOfGridColumns());

		// Setting number of grid columns
		gridView.setNumColumns(pref.getNoOfGridColumns());
		gridView.setColumnWidth(columnWidth);
		gridView.setStretchMode(GridView.NO_STRETCH);
		gridView.setPadding((int) padding, (int) padding, (int) padding,
				(int) padding);

		// Setting horizontal and vertical padding
		gridView.setHorizontalSpacing((int) padding);
		gridView.setVerticalSpacing((int) padding);
	}

}

Now go back to your MainActivity.java, uncomment the GridFragment related code which you commented earlier and run the project. You should able to see the wallpapers in GridView once you selected the category from navigation drawer.

android free wallpapers app grid view

Wallpaper Fullscreen View

We also providing user another option to view selected thumbnail image in fullscreen mode. So to implement this, follow below steps.

27. Create an xml file named activity_fullscreen_image.xml under res ⇒ layout folder. This file contains HorizontalScrollView element to scroll the fullscreen image horizontally. Also it contains two more buttons to provide user option to apply the image as wallpaper and download the wallpaper to galleries.

<?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="@color/black" >

    <ProgressBar
        android:id="@+id/pbLoader"
        style="?android:attr/progressBarStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" >
    </ProgressBar>

    <!-- Scroll view for fullscreen preview -->

    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none" >

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

            <ImageView
                android:id="@+id/imgFullscreen"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitXY" />
        </LinearLayout>
    </HorizontalScrollView>

    <!-- Set as wallpaper button -->

    <LinearLayout
        android:id="@+id/llSetWallpaper"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="10dp"
        android:background="@drawable/btn_rounded_corner"
        android:gravity="center_vertical"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ico_apply" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:text="@string/set_wallpaper"
            android:textColor="@color/white"
            android:textSize="18dp" />
    </LinearLayout>

    <!-- Download wallpaper button -->

    <LinearLayout
        android:id="@+id/llDownloadWallpaper"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="10dp"
        android:background="@drawable/btn_rounded_corner"
        android:gravity="center_vertical"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:src="@drawable/ico_download" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:text="@string/download_wallpaper"
            android:textColor="@color/white"
            android:textSize="18dp" />
    </LinearLayout>

</RelativeLayout>

28. Create a class named FullScreenViewActivity.java under your main package. This class takes care of calculating the image aspect ratio in fullscreen mode. The image width will calculated respective to device height. Below steps will be execute in order show the fullscreen wallpaper.

> User selects the wallpaper from GridView. The selected wallpaper will be passed to fullscreen image activity.
> In fullscreen activity, we make another call to Picasa to get the selected wallpaper’s high resolution version.
> The downloaded wallpaper width will be calculated depending upon device height.
> Then the image will be displayed in ImageView. The HorizontalScrollView make the wallpaper scrollable horizontally.

package info.androidhive.awesomewallpapers;

import info.androidhive.awesomewallpapers.app.AppController;
import info.androidhive.awesomewallpapers.picasa.model.Wallpaper;
import info.androidhive.awesomewallpapers.util.Utils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.android.volley.toolbox.ImageLoader.ImageListener;
import com.android.volley.toolbox.JsonObjectRequest;

public class FullScreenViewActivity extends Activity implements OnClickListener {
	private static final String TAG = FullScreenViewActivity.class
			.getSimpleName();
	public static final String TAG_SEL_IMAGE = "selectedImage";
	private Wallpaper selectedPhoto;
	private ImageView fullImageView;
	private LinearLayout llSetWallpaper, llDownloadWallpaper;
	private Utils utils;
	private ProgressBar pbLoader;

	// Picasa JSON response node keys
	private static final String TAG_ENTRY = "entry",
			TAG_MEDIA_GROUP = "media$group",
			TAG_MEDIA_CONTENT = "media$content", TAG_IMG_URL = "url",
			TAG_IMG_WIDTH = "width", TAG_IMG_HEIGHT = "height";

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

		fullImageView = (ImageView) findViewById(R.id.imgFullscreen);
		llSetWallpaper = (LinearLayout) findViewById(R.id.llSetWallpaper);
		llDownloadWallpaper = (LinearLayout) findViewById(R.id.llDownloadWallpaper);
		pbLoader = (ProgressBar) findViewById(R.id.pbLoader);

		// hide the action bar in fullscreen mode
		getActionBar().hide();

		utils = new Utils(getApplicationContext());

		// layout click listeners
		llSetWallpaper.setOnClickListener(this);
		llDownloadWallpaper.setOnClickListener(this);

		// setting layout buttons alpha/opacity
		llSetWallpaper.getBackground().setAlpha(70);
		llDownloadWallpaper.getBackground().setAlpha(70);

		Intent i = getIntent();
		selectedPhoto = (Wallpaper) i.getSerializableExtra(TAG_SEL_IMAGE);

		// check for selected photo null
		if (selectedPhoto != null) {

			// fetch photo full resolution image by making another json request
			fetchFullResolutionImage();

		} else {
			Toast.makeText(getApplicationContext(),
					getString(R.string.msg_unknown_error), Toast.LENGTH_SHORT)
					.show();
		}
	}

	/**
	 * Fetching image fullresolution json
	 * */
	private void fetchFullResolutionImage() {
		String url = selectedPhoto.getPhotoJson();

		// show loader before making request
		pbLoader.setVisibility(View.VISIBLE);
		llSetWallpaper.setVisibility(View.GONE);
		llDownloadWallpaper.setVisibility(View.GONE);

		// volley's json obj request
		JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET, url,
				null, new Response.Listener<JSONObject>() {

					@Override
					public void onResponse(JSONObject response) {
						Log.d(TAG,
								"Image full resolution json: "
										+ response.toString());
						try {
							// Parsing the json response
							JSONObject entry = response
									.getJSONObject(TAG_ENTRY);

							JSONArray mediacontentArry = entry.getJSONObject(
									TAG_MEDIA_GROUP).getJSONArray(
									TAG_MEDIA_CONTENT);

							JSONObject mediaObj = (JSONObject) mediacontentArry
									.get(0);

							String fullResolutionUrl = mediaObj
									.getString(TAG_IMG_URL);

							// image full resolution widht and height
							final int width = mediaObj.getInt(TAG_IMG_WIDTH);
							final int height = mediaObj.getInt(TAG_IMG_HEIGHT);

							Log.d(TAG, "Full resolution image. url: "
									+ fullResolutionUrl + ", w: " + width
									+ ", h: " + height);

							ImageLoader imageLoader = AppController
									.getInstance().getImageLoader();

							// We download image into ImageView instead of
							// NetworkImageView to have callback methods
							// Currently NetworkImageView doesn't have callback
							// methods

							imageLoader.get(fullResolutionUrl,
									new ImageListener() {

										@Override
										public void onErrorResponse(
												VolleyError arg0) {
											Toast.makeText(
													getApplicationContext(),
													getString(R.string.msg_wall_fetch_error),
													Toast.LENGTH_LONG).show();
										}

										@Override
										public void onResponse(
												ImageContainer response,
												boolean arg1) {
											if (response.getBitmap() != null) {
												// load bitmap into imageview
												fullImageView
														.setImageBitmap(response
																.getBitmap());
												adjustImageAspect(width, height);

												// hide loader and show set &
												// download buttons
												pbLoader.setVisibility(View.GONE);
												llSetWallpaper
														.setVisibility(View.VISIBLE);
												llDownloadWallpaper
														.setVisibility(View.VISIBLE);
											}
										}
									});

						} catch (JSONException e) {
							e.printStackTrace();
							Toast.makeText(getApplicationContext(),
									getString(R.string.msg_unknown_error),
									Toast.LENGTH_LONG).show();
						}

					}
				}, new Response.ErrorListener() {

					@Override
					public void onErrorResponse(VolleyError error) {
						Log.e(TAG, "Error: " + error.getMessage());
						// unable to fetch wallpapers
						// either google username is wrong or
						// devices doesn't have internet connection
						Toast.makeText(getApplicationContext(),
								getString(R.string.msg_wall_fetch_error),
								Toast.LENGTH_LONG).show();

					}
				});

		// Remove the url from cache
		AppController.getInstance().getRequestQueue().getCache().remove(url);

		// Disable the cache for this url, so that it always fetches updated
		// json
		jsonObjReq.setShouldCache(false);

		// Adding request to request queue
		AppController.getInstance().addToRequestQueue(jsonObjReq);
	}

	/**
	 * Adjusting the image aspect ration to scroll horizontally, Image height
	 * will be screen height, width will be calculated respected to height
	 * */
	@SuppressWarnings("deprecation")
	@SuppressLint("NewApi")
	private void adjustImageAspect(int bWidth, int bHeight) {
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

		if (bWidth == 0 || bHeight == 0)
			return;

		int sHeight = 0;

		if (android.os.Build.VERSION.SDK_INT >= 13) {
			Display display = getWindowManager().getDefaultDisplay();
			Point size = new Point();
			display.getSize(size);
			sHeight = size.y;
		} else {
			Display display = getWindowManager().getDefaultDisplay();
			sHeight = display.getHeight();
		}

		int new_width = (int) Math.floor((double) bWidth * (double) sHeight
				/ (double) bHeight);
		params.width = new_width;
		params.height = sHeight;

		Log.d(TAG, "Fullscreen image new dimensions: w = " + new_width
				+ ", h = " + sHeight);

		fullImageView.setLayoutParams(params);
	}

	/**
	 * View click listener
	 * */
	@Override
	public void onClick(View v) {
		Bitmap bitmap = ((BitmapDrawable) fullImageView.getDrawable())
				.getBitmap();
		switch (v.getId()) {
		// button Download Wallpaper tapped
		case R.id.llDownloadWallpaper:
			utils.saveImageToSDCard(bitmap);
			break;
		// button Set As Wallpaper tapped
		case R.id.llSetWallpaper:
			utils.setAsWallpaper(bitmap);
			break;
		default:
			break;
		}

	}
}

29. Add the FullScreenViewActivity entry in AndroidManifest.xml file between <application> tags.

<application ...>       
        <activity
            android:name="info.androidhive.awesomewallpapers.FullScreenViewActivity"
            android:screenOrientation="portrait" >
        </activity>
        </activity>
</application>

Now run the project and select any image from grid view. You should able see fullscreen image activity launched with wallpaper image preview.

android free wallpapers app grid view

Providing Set as Wallpaper Option

30. To apply the wallpaper to device, add a click listener to set as wallpaper button and call setAsWallpaper() method presented in Utils.java class

Add below line in onCreate() method of FullScreenViewActivity.java

llSetWallpaper.setOnClickListener(this);

Call below method in onClick() method of FullScreenViewActivity.java

	/**
	 * View click listener
	 * */
	@Override
	public void onClick(View v) {
		Bitmap bitmap = ((BitmapDrawable) fullImageView.getDrawable())
				.getBitmap();
		switch (v.getId()) {		
		case R.id.llSetWallpaper:
			utils.setAsWallpaper(bitmap);
			break;
		default:
			break;
		}

	}

Now if you tap the Set button, the wallpaper will be applied to device.

android free wallpapers set as wallpaper

Downloading Wallpaper to Gallery

31. Just like set as wallpaper, to download wallpaper to device gallery directory, add the click listener to download button and call saveImageToSDCard() method presented in Utils.java

Add below line in onCreate() method of FullScreenViewActivity.java

llDownloadWallpaper.setOnClickListener(this);

Add another case statement in onClick() method of FullScreenViewActivity.java

	/**
	 * View click listener
	 * */
	@Override
	public void onClick(View v) {
		Bitmap bitmap = ((BitmapDrawable) fullImageView.getDrawable())
				.getBitmap();
		switch (v.getId()) {
		// button Download Wallpaper tapped
		case R.id.llDownloadWallpaper:
			utils.saveImageToSDCard(bitmap);
			break;
		// button Set As Wallpaper tapped
		case R.id.llSetWallpaper:
			utils.setAsWallpaper(bitmap);
			break;
		default:
			break;
		}

	}

Now if you tap Download Wallpaper button, the wallpaper will be downloaded to your gallery with album named Awesome Wallpapers. If you don’t see the album there, reboot your device. I couldn’t see the album created until I rebooted my device. I am yet to find the issue 🙁

With this we almost the completed the app. But lastly we need to add a Settings screen where user can configure Picasa username, number of grid columns and gallery directory name. This step is not necessary if you are planning to release this app in playstore. It is just for the developers who is reading this.

Adding Settings Screen

32. . Create a layout file named activity_settings.xml under res layout folder. This layout contains a form with few edittext fields and a save button.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginTop="15dp"
        android:text="@string/lbl_google_username"
        android:textColor="@color/settings_label"
        android:textSize="16dp" />

    <EditText
        android:id="@+id/txtGoogleUsername"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:background="@drawable/edittext_rounded_corner"
        android:inputType="text"
        android:singleLine="true" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="@string/lbl_no_grid_columns"
        android:textColor="@color/settings_label"
        android:textSize="16dp" />

    <EditText
        android:id="@+id/txtNoOfColumns"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:background="@drawable/edittext_rounded_corner"
        android:inputType="number"
        android:singleLine="true" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:text="@string/lbl_gallery_name"
        android:textColor="@color/settings_label"
        android:textSize="16dp" />

    <EditText
        android:id="@+id/txtGalleryName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="25dp"
        android:background="@drawable/edittext_rounded_corner"
        android:singleLine="true" />

    <Button
        android:id="@+id/btnSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/btn_rounded_corner"
        android:paddingLeft="30dp"
        android:paddingRight="30dp"
        android:text="@string/lbl_btn_save"
        android:textColor="@color/white"
        android:textSize="18dp" />

</LinearLayout>

33. . Create a class named SettingsActivity.java and add the below code. This code just validates the data entered by user and overwrites the respective values in Shared Preferences.

package info.androidhive.awesomewallpapers;

import info.androidhive.awesomewallpapers.R;
import info.androidhive.awesomewallpapers.util.PrefManager;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class SettingsActivity extends Activity {
	private PrefManager pref;
	private TextView txtGoogleUsername, txtNoOfGridColumns, txtGalleryName;
	private Button btnSave;

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

		txtGoogleUsername = (TextView) findViewById(R.id.txtGoogleUsername);
		txtNoOfGridColumns = (TextView) findViewById(R.id.txtNoOfColumns);
		txtGalleryName = (TextView) findViewById(R.id.txtGalleryName);
		btnSave = (Button) findViewById(R.id.btnSave);

		pref = new PrefManager(getApplicationContext());

		// Display edittext values stored in shared preferences
		// Google username
		txtGoogleUsername.setText(pref.getGoogleUserName());

		// Number of grid columns
		txtNoOfGridColumns.setText(String.valueOf(pref.getNoOfGridColumns()));

		// Gallery name
		txtGalleryName.setText(pref.getGalleryName());

		// Save settings button click listener
		btnSave.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {

				// Validating the data before saving to shared preferences
				// validate google username
				String googleUsername = txtGoogleUsername.getText().toString()
						.trim();
				if (googleUsername.length() == 0) {
					Toast.makeText(getApplicationContext(),
							getString(R.string.toast_enter_google_username),
							Toast.LENGTH_LONG).show();
					return;
				}

				// validate number of grid columns
				String no_of_columns = txtNoOfGridColumns.getText().toString()
						.trim();
				if (no_of_columns.length() == 0 || !isInteger(no_of_columns)) {
					Toast.makeText(getApplicationContext(),
							getString(R.string.toast_enter_valid_grid_columns),
							Toast.LENGTH_LONG).show();
					return;
				}

				// validate gallery name
				String galleryName = txtGalleryName.getText().toString().trim();
				if (galleryName.length() == 0) {
					Toast.makeText(getApplicationContext(),
							getString(R.string.toast_enter_gallery_name),
							Toast.LENGTH_LONG).show();
					return;
				}

				// Check for setting changes
				if (!googleUsername.equalsIgnoreCase(pref.getGoogleUserName())
						|| !no_of_columns.equalsIgnoreCase(String.valueOf(pref
								.getNoOfGridColumns()))
						|| !galleryName.equalsIgnoreCase(pref.getGalleryName())) {
					// User changed the settings
					// save the changes and launch SplashScreen to initialize
					// the app again
					pref.setGoogleUsername(googleUsername);
					pref.setNoOfGridColumns(Integer.parseInt(no_of_columns));
					pref.setGalleryName(galleryName);

					// start the app from SplashScreen
					Intent i = new Intent(SettingsActivity.this,
							SplashActivity.class);
					// Clear all the previous activities
					i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
							| Intent.FLAG_ACTIVITY_CLEAR_TASK);
					startActivity(i);
				} else {
					// user not modified any values in the form
					// skip saving to shared preferences
					// just go back to previous activity
					onBackPressed();
				}

			}
		});

	}

	public boolean isInteger(String input) {
		try {
			Integer.parseInt(input);
			return true;
		} catch (Exception e) {
			return false;
		}
	}
}

34. Finally add settings activity entry in AndroidManifest.xml

    <application ...>        
        <activity
            android:name="info.androidhive.awesomewallpapers.SettingsActivity"
            android:label="@string/action_settings"
            android:screenOrientation="portrait" >
        </activity>
    </application>

Finally your AndroidManifest.xml file should look like this.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.awesomewallpapers"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />

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

    <application
        android:name="info.androidhive.awesomewallpapers.app.AppController"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/FreeWallTheme" >
        <activity
            android:name="info.androidhive.awesomewallpapers.SplashActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="info.androidhive.awesomewallpapers.MainActivity"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name="info.androidhive.awesomewallpapers.FullScreenViewActivity"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name="info.androidhive.awesomewallpapers.SettingsActivity"
            android:label="@string/action_settings"
            android:screenOrientation="portrait" >
        </activity>
    </application>

</manifest>

Run the app and launch settings screen by tapping overflow icon on action bar.

Congratulations 🙂 If you are succeeded all the steps until now, you just create a fully fledged wallpapers app which has good potential go into market right away. But before that I would like to address few important points to you.

> This app is doesn’t supports older versions < 4.0. For that you need to use Android Support Library to provide backward compatibility.

> Even though we are using Google+ / Picasa web services to provide wallpapers, in real scenario we should have a server side technology to detect the mobile device and respond the wallpapers depending on mobile configuration like screen dimensions.

If you have any queries or suggestions please leave in comment section below.

Subscribe
Notify of
guest
188 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
EhteshamMehmood
EhteshamMehmood
6 years ago

Its Awsome <3 🙂

kimcy
kimcy
6 years ago

Thank you very much, I used to Picassa AP, I think google support quite bad, several api can’t use. I tried create small application with it
https://play.google.com/store/apps/details?id=com.kimcy92.mywallpaper

Rony Rahmawan
Rony Rahmawan
6 years ago

wrong video demo? 🙂

Ravi Tamada
6 years ago
Reply to  Rony Rahmawan

Thanks. Let me check.

android apk
android apk
6 years ago

He Ravi i want to Add Website Redirection in Dialog Box. When anyone Open the App or Game 1st Open the Website & After the Game Will Start. Only 1st Time Online. I have this Code in smali can you Please give me Complete Code with Website Redirection.

new-instance v0, Landroid/app/AlertDialog$Builder;

invoke-direct {v0, p0}, Landroid/app/AlertDialog$Builder;->(Landroid/content/Context;)V

const-string v1, “”

invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;->setTitle(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;

move-result-object v0

const-string v1, “”

invoke-virtual {v0, v1}, Landroid/app/AlertDialog$Builder;->setMessage(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;

move-result-object v0

const-string v1, “”

const/4 v2, 0x0

invoke-virtual {v0, v1, v2}, Landroid/app/AlertDialog$Builder;->setPositiveButton(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;

move-result-object v0

invoke-virtual {v0}, Landroid/app/AlertDialog$Builder;->show()Landroid/app/AlertDialog;

Yadnyesh
Yadnyesh
6 years ago

i am using navigation drawer in my android app..
Each of fragment contains async task which getting data from internet and displaying in custom list..

But when i am switching between fragments an async task started loading data again..
So how to save state of fragment

Ravi Tamada
6 years ago
Reply to  Yadnyesh

If you use volley all the requests will be singleton. Using request tag you can identify the request. Before make the request check in the request queue using the tag, if request is not present send the request again.

Arjun
Arjun
6 years ago

There is no “but_rounded_corner” and “list_iterater” in drawable folders and Under which package we need to create a LruBitmapCache and SettingsActivity . Please provide the info

Ravi Tamada
6 years ago
Reply to  Arjun

It doesn’t matter under which package you create the class. But for organizing the project, we keep them in separate packages.

Create LruBitmapCache.java under util package. It seems I forgot to add code for but_rounded_corder. For now you can get the code from downloaded project.

Arjun
Arjun
6 years ago
Reply to  Ravi Tamada

Ok 🙂

Daniel
Daniel
6 years ago

How can i remove the horizontal scroll view and fit full image on the screen. even if is scaled so it fits.

Thanks.

Guest
Guest
6 years ago

Hi Ravi nice tutorial.. i have doubt. I saved the wall paper but I couldn’t find the saved picture in awesome wallpaper folder. what may be the issue? Thanks in advance

Ravi Tamada
6 years ago
Reply to  Guest

Yeah. I too even found this issue. You can see the downloaded wallpapers once you reboot your mobile. Search for “android refresh gallery album after save”.

Sanjay Sinalkar
Sanjay Sinalkar
6 years ago

Hello Dude, I am getting this Server error

Error 503 Service Unavailable

Service Unavailable

Guru Meditation:

XID: 1159377834

Varnish cache server

May be you have installed more than one caching tool ,,…anyway
You wrote awesome tutorials! There is one suggestion ,can you please create category-wise and chapter-wise post like Android Beginner to Intermediate in one page and link there it will be easy to learn as reader in flow and reader will continues to next tutorials
Thanks

Brce
Brce
6 years ago

Hi Ravi nice tutorial. If I want to remove particular title in menu items. Is it possible to do in android without deleting album title in picasa?

Milind Audichya
Milind Audichya
6 years ago

Hello Ravi, Thanx for this great tutorial..
I have developed an application with the help of the same and deployed it on Google Play Store..
But its the second time when they removed my application by giving the following reason :

“REASON FOR REMOVAL: Violation of the intellectual property and impersonation or deceptive behavior provisions of the Content Policy. Please refer to the IP infringement and impersonation policy help article for more information.”

What can i do for the same ?

Ravi Tamada
6 years ago

This is because due to copyright issues. If you are directly using the wallpapers used in this tutorial, it will be copyright issue as they won’t comes under fee license.

Milind Audichya
Milind Audichya
6 years ago
Reply to  Ravi Tamada

Thanks for your kind reply.. Kindly suggest what can i do further for the same please if you can

Priya kuchan
Priya kuchan
6 years ago

Hi ravi please drop sample code for supporting multiple screens in andoird

Nilu Patel
6 years ago

Dear Ravi Sir,

On Click Recently Added, Volley getting Error: Could not Delete cache entry for key=https://picasaweb.google.com/data/feed/api/user/nilay.scet?albumid/5637447830974140801?alt=json, filename=-1830143455-280059811

and also give same error in Profile Photos

Brce
Brce
6 years ago

Hi Ravi. why it takes more time to display the image though using image loader?

Ravi Tamada
6 years ago
Reply to  Brce

I guess because of image size. All the images are of 1 MB approx.

Hoangdata
Hoangdata
6 years ago

Thank you for great tutorial. I think this error when “if you tap Download Wallpaper button, the wallpaper will be downloaded to your gallery with album named Awesome Wallpapers. If you don’t see the album there, reboot your device. I couldn’t see the album created until I rebooted my device.”

I think maybe store image file on media store through this method:

public static void addImageToGallery(final String filePath, final Context context) {
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, “image/jpeg”);
values.put(MediaStore.MediaColumns.DATA, filePath);
context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
}

I try this method and solve this issue.

Ravi Tamada
6 years ago
Reply to  Hoangdata

Thanks Hoangdata for your valuable tip.

allison
allison
6 years ago

Please help me
start load 10 picture and i click load then load 10 pic next

Constantine
Constantine
6 years ago

Hello Ravi, thank you for this awesome tutorial. But unfortunatelly I have a NullPointerException in MainActivity. Debugger indicates that albumsList = AppController.getInstance().getPrefManger().getCategories(); equals null. Please tell me, how do you think, where there may be an error?

Hoangdata
Hoangdata
6 years ago
Reply to  Constantine

You must place “android:name=.app.AppController” in in AndroidManifest.xml to load app controller before run application

Constantine
Constantine
6 years ago
Reply to  Hoangdata

Oh, it works! Thank you!

Hoangdata
Hoangdata
6 years ago

I want to use Pageradapter to show image through slider. When I click a thumbnail in gridview, so show full image but how to load all image from url just like grid view…

Pawan Ratre Gurjar
Pawan Ratre Gurjar
6 years ago

Hello Ravi Sir

I have to show loading image before image comes from Any Url…

I am using Volley Networkimage…

If any good method available then plz suggest me…

Also if image size is not fix i mean image can be a Rectangle or an square SHAPE then how can we make a rounded corner image of a Volley Networkimage

meenu
meenu
6 years ago

Hello Ravi Sir,
How to add different image icon to navigation drawer..??

AK
AK
6 years ago

Hi Ravi nice tutorial.. i have doubt. I saved the wall paper but I couldn’t find the saved picture in Gallery but it’s exist storage/pictures/awesome wallpapers. what may be the issue? Please solve the problem and update the code. Thanks in advance

Juned
Juned
6 years ago
Reply to  AK

same problem with mine

Juned
Juned
6 years ago
Reply to  AK

Did you find out any solution ?

Ravi Tamada
6 years ago
Reply to  Juned

Even I got the same problem. The album appeared once the device got restarted.

Juned Maknojiya
6 years ago
Reply to  Ravi Tamada

is there any way we can refresh a gallery without rebooting a device?

AK
AK
6 years ago

(1) How to show Navigation Drawer on Starting of Apps and (2)? How to show Navigation Drawer List if we press back button and on press of again back button then Exit.

AK
AK
6 years ago

I Called to the openDrawer method in the main activity:

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

switch(keyCode)

{
case KeyEvent.KEYCODE_BACK:
mDrawerLayout.openDrawer(Gravity.LEFT);
}

return super.onKeyDown(keyCode, event);
}
The fact is that there was a little sliding movement (very quick), and then back to hide. After that i figured out that there was sliding while i held the back button pressed, but if i released it, the side menu went back again to original hided position.

What am i doing wrong please Help me?? Thanx in advance.

AK
AK
6 years ago

I Called to the openDrawer method in the main activity:

@Override

public void onBackPressed() {

if (!mDrawerLayout.isDrawerOpen(mDrawerList)) {

mDrawerLayout.openDrawer(mDrawerList);

}

// super.onBackPressed();
}

From this Method Drawer open Correctly on Back Press but Again on Press of Back Button Activity Not close, and if we use super.onBackPressed(); it close immediately after showing drawer. Please Sir Give Solution …How to show Navigation Drawer List if we press back button and on press of again back button then Exit??. I’m Newbie.

fdson
fdson
6 years ago

wallpaper not scrolling in kitkat v4.4.4..please help

fdson
fdson
6 years ago

This app is working perfectly on v4.4.2 but after i updated my device to v4.4.4 when i set the wallpaper ,the wallpaper is not scrolling any more ..it is fixed to one screen…please help

fdson
fdson
6 years ago

Ravi Sir i need your help really fast ..thanx

spitfire10
spitfire10
6 years ago

Hi Ravi, would like to check with you, if I would like to only display just 1 or 2 albums from the PicasaWeb which code should I make the changes?

Am just started out to learn the Android prog.

Appreciated if you could shed me some light on tat..

Thanks
Fire

fdson
fdson
6 years ago

Ravi Sir can you please help me..can i expect any help from your side????????

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago

Thanx Ravi for this nice tutorial….. because of you i m able to create this app within one day….apart from one error…..whenever i click the image for full screen its giving me this error ” unfortunately awesome wallpapers has stopped ” i checked all files but not able to find the solution or this. kindly help me.

thank you

Ravi Tamada
6 years ago

Check your Eclipse LogCat for crash report.

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago
Reply to  Ravi Tamada

09-21 15:45:45.950: E/AndroidRuntime(6967): FATAL EXCEPTION: main

09-21 15:45:45.950: E/AndroidRuntime(6967): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.awesomequotes/com.example.awesomequotes.FullScreenViewActivity}: java.lang.NullPointerException

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2355)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread.access$600(ActivityThread.java:151)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1335)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.os.Handler.dispatchMessage(Handler.java:99)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.os.Looper.loop(Looper.java:155)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread.main(ActivityThread.java:5520)

09-21 15:45:45.950: E/AndroidRuntime(6967): at java.lang.reflect.Method.invokeNative(Native Method)

09-21 15:45:45.950: E/AndroidRuntime(6967): at java.lang.reflect.Method.invoke(Method.java:511)

09-21 15:45:45.950: E/AndroidRuntime(6967): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)

09-21 15:45:45.950: E/AndroidRuntime(6967): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)

09-21 15:45:45.950: E/AndroidRuntime(6967): at dalvik.system.NativeStart.main(Native Method)

09-21 15:45:45.950: E/AndroidRuntime(6967): Caused by: java.lang.NullPointerException

09-21 15:45:45.950: E/AndroidRuntime(6967): at com.example.awesomequotes.FullScreenViewActivity.onCreate(FullScreenViewActivity.java:54)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.Activity.performCreate(Activity.java:5066)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1101)

09-21 15:45:45.950: E/AndroidRuntime(6967): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2311)

09-21 15:45:45.950: E/AndroidRuntime(6967): … 11 more

my app name is awesomequotes

Ravi Tamada
6 years ago

Does your layout file contains the elements whatever I have for FullScreenViewActivity ?

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago
Reply to  Ravi Tamada

i have double checked FullScreenViewActivity …..not able to find any error!
any other solution?

Juned Maknojiya
6 years ago

I was facing a same issue.. I tried with a new eclipse and its solved 🙂

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago

you created the same project in eclipse different version? i will try that….. any other modifications?

Juned Maknojiya
6 years ago

I have tried with a latest version.. with no changes on a source code

btw I am facing another problem in a downloading a images..

once we click on a download .. we can not see a image in a gallery unless we reboot a device.. is there any solution ??

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago

I think maybe store image file on media store through this method: try this

public static void addImageToGallery(final String filePath, final Context context) {
ContentValues values = new ContentValues();
values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(Images.Media.MIME_TYPE, “image/jpeg”);
values.put(MediaStore.MediaColumns.DATA, filePath);
context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
}

could you pls send me the link to download new eclipse version….i m not able to find it?
thank u

Moktar Hossain
Moktar Hossain
6 years ago

Thanx Ravi Bhai to give awesome wallpapers app. I create this app one day with your instruction and run rightly without error also try this app my own picasa web album. It’s really excellent app.

Ravi Tamada
6 years ago
Reply to  Moktar Hossain

Hi Moktar, I am glad that you find if very useful 🙂

Sahitya Kumar Suman
Sahitya Kumar Suman
5 years ago
Reply to  Ravi Tamada

@moktar Hossain

I ran the app and was able to load the pictures in the “Recently Added” tab without any problems. But however when I click other categories I get the toast message “Sorry! Unable to fetch wallpaper(s). Verify app settings or device doesn’t have internet connection” which is being generated from the onErrorResponse() in the GridFragment class,how can I go about this problem my internet connection works just fine.

I got one answer about this that i should change the username in AppCont …
which username should i put into it ….. or there is different username for picasa albums available if not then tell me where i can get the username ……

Thnx in advance

Muklas
Muklas
6 years ago

is that posible to use google product into our app… if this publish in google play ?
because they do not allowed to use of any google product in android app ?

Ravi Tamada
6 years ago
Reply to  Muklas

I am not sure.

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago

Hello everyone, I have created this app. Apart from “Set the wallpaper” & “Download the Image” feature i want to add “share the image to Facebook” feature in the app. Can anyone help me with that?

Thank you

kimcy
kimcy
6 years ago

Thank you Ravi very much. I improve your application and add function crop image when set wallpaper , change save image into internal memory(quite bad), because when save into Sdcard gallery not scan image :(. and create selector when press button :).

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago
Reply to  kimcy

hello kimcy…..I have downloaded your app “Android HD Wallpapers” from play store.and i like the functions you have added. You also added share the wallpaper to facebook function. I also want to add that function in my app.can you pls help me?

thank you

nature
nature
6 years ago

Hi Nishant Jaisinghani you can use like this to share image on facebook or whatsapp or anywhere..
public void shareImage(){
BitmapDrawable bitmapDrawable = (BitmapDrawable)fullImageView.getDrawable();
Bitmap bitmap = bitmapDrawable.getBitmap();
// Save this bitmap to a file.
File cache = this.getExternalCacheDir();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
File sharefile = new File(cache, “Wallpaper-” + n + “.jpg”); //give your name and save it.
try {
FileOutputStream out = new FileOutputStream(sharefile);

bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

out.flush();

out.close();

} catch (IOException e) {

}

// Now send it out to share

Intent share = new Intent(android.content.Intent.ACTION_SEND);

share.setType(“image/*”);

share.putExtra(Intent.EXTRA_STREAM, Uri.parse(“file://” + sharefile));

try {

this.startActivity(Intent.createChooser(share, “Share photo”));

} catch (Exception e) {

}

}
return true;
}

}

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago
Reply to  nature

Thanks for your help….i am little bit confused….where should i put up the code you provided on FullScreenViewActivity.java or MainActivity.java…… and i want the share to facebook icon just between the set as wallpaper and download the wallpaper icons during full screen image….could u please provide the full code.Thank You

nature
nature
6 years ago

It’s your requirement how to use ie you want to use in button or in menu..for eg: i am showing it in menu:

FullScreenViewActivity:

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main_menu, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle presses on the action bar items

switch (item.getItemId()) {

case R.id.share:

BitmapDrawable bitmapDrawable = (BitmapDrawable)fullImageView.getDrawable(); // here fullImageView is object of ImageView

Bitmap bitmap = bitmapDrawable.getBitmap();

// Save this bitmap to a file.

File cache = this.getExternalCacheDir();

Random generator = new Random();

int n = 10000;

n = generator.nextInt(n);

File sharefile = new File(cache, “Wallpaper-” + n + “.jpg”); //give your name and save it.

try {

FileOutputStream out = new FileOutputStream(sharefile);

bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

out.flush();

out.close();

} catch (IOException e) {

}

// Now send it out to share

Intent share = new Intent(android.content.Intent.ACTION_SEND);

share.setType(“image/*”);

share.putExtra(Intent.EXTRA_STREAM, Uri.parse(“file://” + sharefile));

try {

this.startActivity(Intent.createChooser(share, “Share photo”));

} catch (Exception e) {

}

}

return true;

}

}

main_menu.xml:

if you want to use that in button, simple just use that code in button click 🙂 still if you have doubt, you can refer this. http://ramkumarhelios.blogspot.in/2014/09/displaying-images-form-list-of-urls-in.html

Capkin
Capkin
6 years ago
Reply to  nature

Hi, this is very helpful thanks a lot, can you give me the complet code? and I have same more questions can you help me?

xanjay
6 years ago
Reply to  kimcy

i want the playstore link of your app

ERKAN BEŞALTI
ERKAN BEŞALTI
6 years ago

Hi Ravi!
Your tutorials helping us amateurs so much! I need help with something. As you know you can enter titles under each photo in your Picasa album. Can we get and show those titles under the walpapers when in full screen view?

Dharun
Dharun
6 years ago

Hi Ravi,
I don’t have error in these code, but unfortunately app has stopped, I check manifest file,,but it’s not.help
thanks
Dharun

Aldo Cano
Aldo Cano
6 years ago

Hi ravi , i want to know how to grab wallpapers from server location and not to use galleries from picasa.

nature
nature
6 years ago

Hi Ravi, how to display like separation of load of images like first 10 and then while scrolling next 10 like that? instead of displaying all at a time? since it takes more time to load.

Guest
Guest
6 years ago

where is the btn_rounded_corner

Nishant Jaisinghani
Nishant Jaisinghani
6 years ago
Reply to  Guest

Download The code from this page and you will find it in the folder.

ShivamDev
ShivamDev
5 years ago

@Nishant are you talking about res code or project code as I cant find the project code and res folder does not have it

Guest
Guest
6 years ago

Hi ravi.
It works fine but i want to change the URL to my picasa account to see my photos and albums,so where actually i have to change the URL…?
As you mentioned i have changed the user name but not woking. Do help me please

ShivamDev
ShivamDev
5 years ago
Reply to  Guest

change the username in AppConst class

Capkin
Capkin
6 years ago

10-26 00:28:21.360: D/AndroidRuntime(3295): Shutting down VM

10-26 00:28:21.360: W/dalvikvm(3295): threadid=1: thread exiting with uncaught exception (group=0x41e322a0)

10-26 00:28:21.360: E/AndroidRuntime(3295): FATAL EXCEPTION: main

10-26 00:28:21.360: E/AndroidRuntime(3295): java.lang.RuntimeException: Unable to instantiate application info.androidhive.awesomewallpapers.app.AppController: java.lang.ClassNotFoundException: info.androidhive.awesomewallpapers.app.AppController

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.LoadedApk.makeApplication(LoadedApk.java:501)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4170)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.ActivityThread.access$1400(ActivityThread.java:134)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.os.Handler.dispatchMessage(Handler.java:99)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.os.Looper.loop(Looper.java:137)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.ActivityThread.main(ActivityThread.java:4867)

10-26 00:28:21.360: E/AndroidRuntime(3295): at java.lang.reflect.Method.invokeNative(Native Method)

10-26 00:28:21.360: E/AndroidRuntime(3295): at java.lang.reflect.Method.invoke(Method.java:511)

10-26 00:28:21.360: E/AndroidRuntime(3295): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)

10-26 00:28:21.360: E/AndroidRuntime(3295): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)

10-26 00:28:21.360: E/AndroidRuntime(3295): at dalvik.system.NativeStart.main(Native Method)

10-26 00:28:21.360: E/AndroidRuntime(3295): Caused by: java.lang.ClassNotFoundException: info.androidhive.awesomewallpapers.app.AppController

10-26 00:28:21.360: E/AndroidRuntime(3295): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)

10-26 00:28:21.360: E/AndroidRuntime(3295): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)

10-26 00:28:21.360: E/AndroidRuntime(3295): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.Instrumentation.newApplication(Instrumentation.java:982)

10-26 00:28:21.360: E/AndroidRuntime(3295): at android.app.LoadedApk.makeApplication(LoadedApk.java:496)

10-26 00:28:21.360: E/AndroidRuntime(3295): … 11 more

what did I wrong?

Nomas
Nomas
6 years ago

Hi Ravi! Great tutorial! It works perfect. I am trying to change the code a little bit and instead of using gridview I am trying to use listview in fragments but I get NullPointerException and especially when I am calling adapter.notifyDataSetChanged();

🙁

Any ideas why this is happening?

11-01 14:31:33.666: D/AndroidRuntime(17391): Shutting down VM
11-01 14:31:33.666: W/dalvikvm(17391): threadid=1: thread exiting with uncaught exception (group=0x41855da0)
11-01 14:31:33.666: E/AndroidRuntime(17391): FATAL EXCEPTION: main
11-01 14:31:33.666: E/AndroidRuntime(17391): Process: info.androidhive.awesomewallpapers, PID: 17391
11-01 14:31:33.666: E/AndroidRuntime(17391): java.lang.NullPointerException
11-01 14:31:33.666: E/AndroidRuntime(17391): at info.androidhive.awesomewallpapers.MyListFragment$1.onResponse(MyListFragment.java:100)
11-01 14:31:33.666: E/AndroidRuntime(17391): at info.androidhive.awesomewallpapers.MyListFragment$1.onResponse(MyListFragment.java:1)
11-01 14:31:33.666: E/AndroidRuntime(17391): at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
11-01 14:31:33.666: E/AndroidRuntime(17391): at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
11-01 14:31:33.666: E/AndroidRuntime(17391): at android.os.Handler.handleCallback(Handler.java:733)
11-01 14:31:33.666: E/AndroidRuntime(17391): at android.os.Handler.dispatchMessage(Handler.java:95)
11-01 14:31:33.666: E/AndroidRuntime(17391): at android.os.Looper.loop(Looper.java:136)
11-01 14:31:33.666: E/AndroidRuntime(17391): at android.app.ActivityThread.main(ActivityThread.java:5586)
11-01 14:31:33.666: E/AndroidRuntime(17391): at java.lang.reflect.Method.invokeNative(Native Method)
11-01 14:31:33.666: E/AndroidRuntime(17391): at java.lang.reflect.Method.invoke(Method.java:515)
11-01 14:31:33.666: E/AndroidRuntime(17391): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
11-01 14:31:33.666: E/AndroidRuntime(17391): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
11-01 14:31:33.666: E/AndroidRuntime(17391): at dalvik.system.NativeStart.main(Native Method)
11-01 14:31:35.016: I/Process(17391): Sending signal. PID: 17391 SIG: 9

Husam Malaka
Husam Malaka
6 years ago

great tutorial. but how can i swipe left right to the next previous images in my picasa album

alya
alya
6 years ago

i want to crop image before setting wallpaper ..please help

r
r
6 years ago
Reply to  alya

hi
use edmodo crop library

alya
alya
6 years ago
Reply to  r

can you give me the code to crop images and set wallpaper

Khan
Khan
6 years ago

Source code is not Downloading
Plz Do something

alex
alex
6 years ago

HI Ravi I had an issue where i couldn’t see the images after i I downloaded unless i restarted my phone or tablet but after looking around I found this:

// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(_context,
new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i(“ExternalStorage”, “Scanned ” + path + “:”);
Log.i(“ExternalStorage”, “-> uri=” + uri);
}
});
I added to the “saveImageToSDCard(Bitmap bitmap)” method right after the output stream is closed and that resolved the problem.

r
r
6 years ago
Reply to  alex

tnx alex i use your code

alex
alex
6 years ago
Reply to  r

I have another issue, the app shows nothing in the recently added category when loaded, all the other other categories work but I just have a spinner in the GridFragment when recently added is selected. This is the url for my recently added category: “https://picasaweb.google.com/data/feed/api/user/117701736405365918663?kind=photo&alt=json”

I get a json output when I paste it in my browser but no pictures are loaded in the app for recently added. I have no idea why. could you help

Ravi Tamada
6 years ago
Reply to  alex

They will load, but it will take sometime due to cache validation.

alex
alex
6 years ago
Reply to  Ravi Tamada

Is there anyway i could speed the process? like for example only load like the first 20 pictures or any other solution?

alex
alex
6 years ago
Reply to  alex

Never mind Ravi, I forgot to un-comment some lines of code.

Ravi Tamada
6 years ago
Reply to  alex

Ok.

alex
alex
6 years ago

I also had an issue where the AppController.getInstance() was returning a null value; I am not sure how Extending the Application class works, so I made AppController a Regular class, Add a global context variable and overrode the get instance method.

public class AppController {

…..
private static Context mContext;

private AppController(Context context){

mContext = context;

pref = new PrefManager(context);

}

public static synchronized AppController getInstance() {

return mInstance;

}

public static synchronized AppController getInstance(Context context) {

if (mInstance == null) {

mInstance = new AppController(context);

}

return mInstance;

}

…..

}

I then Inititialize AppController in SplashActivity right after setContentView.

deni777
deni777
6 years ago

How to remove settings screen?

Ravi Tamada
5 years ago
Reply to  deni777

You can hide anything, if you don’t wanna show to users.

Example: if you wanna hide your Google User Name, you can modify the SettingsActivity file by changing it in this way-

txtGoogleUsername = (TextView) findViewById(R.id.txtGoogleUsername);

txtGoogleUsername.setVisibility(View.GONE);

Hope this helps you 🙂

deni777
deni777
5 years ago
Reply to  Ravi Tamada

Thank you for your answer Ravi.Can you help me with only one thing.On preview wallpapers are with low quality.I upload wallpapers with size 2560×1600 with size 4mb.When i download this wallpaper on my device he is with same size but is compressed to 2mb.I want wallpaper to be in full resolution.Is this possible.Sorry for my English 😀

MackAttack
MackAttack
6 years ago

This is line is giving me a nullpointerexception

// Picasa request to get list of albums

String url = AppConst.URL_PICASA_ALBUMS.replace(“_PICASA_USER_”, AppController.getInstance()
.getPrefManger().getGoogleUserName());

anyone any ideas??

MackAttack
MackAttack
6 years ago
Reply to  MackAttack

solved this the other day but cant remember how i solved it.

Michael B. Rasmussen
6 years ago

Hey

Thank you for an awesome tutorial straight forward an easy.

I am struggling a little with image sizes and was wondering if you could explain how the Image full resolution url is created?

Michael B. Rasmussen
6 years ago

Never mind found it 🙂

If anyone else as problems with image too large edit the following in Gridfragments:
From:

###
String photoJson = photoObj.getJSONObject(

TAG_ID).getString(TAG_T)

+ “&imgmax=d”;

To:

###

String photoJson = photoObj.getJSONObject(

TAG_ID).getString(TAG_T)

+ “&imgmax=1600”;

MackAttack
MackAttack
6 years ago

IS this for re-sizing on device?

Michael B. Rasmussen
6 years ago
Reply to  MackAttack

No this ony fetches a smaller version of the image from picasa.

MackAttack
MackAttack
6 years ago

Ok thanks! i wonder if its possible to add a function which resizes the full screen pictures relative to the device the app is being run on so that the picture isnt too big for the screen..

Michael B. Rasmussen
6 years ago
Reply to  MackAttack

I think it is I am working on something with pinch zoom I let you know if i get it to work.

Phenil Buch
Phenil Buch
5 years ago

Hey Michael! Did you get pinch zoom to work? I want it in my app so would be very helpful! 🙂

Michael B. Rasmussen
5 years ago
Reply to  Phenil Buch

Sorry got stuck in other dev projects, so didn’t look further into it

188
0
Would love your thoughts, please comment.x
()
x