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.
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
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>
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.
package info.androidhive.awesomewallpapers; public class NavDrawerItem { private String albumId, albumTitle; // boolean flag to check for recent album private boolean isRecentAlbum = false; public NavDrawerItem() { } public NavDrawerItem(String albumId, String albumTitle) { this.albumId = albumId; this.albumTitle = albumTitle; } public NavDrawerItem(String albumId, String albumTitle, boolean isRecentAlbum) { this.albumTitle = albumTitle; this.isRecentAlbum = isRecentAlbum; } public String getAlbumId() { return albumId; } public void setAlbumId(String albumId) { this.albumId = albumId; } public String getTitle() { return this.albumTitle; } public void setTitle(String title) { this.albumTitle = title; } public boolean isRecentAlbum() { return isRecentAlbum; } public void setRecentAlbum(boolean isRecentAlbum) { this.isRecentAlbum = isRecentAlbum; } }
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.
package info.androidhive.awesomewallpapers.helper; import info.androidhive.awesomewallpapers.NavDrawerItem; import info.androidhive.awesomewallpapers.R; import java.util.ArrayList; 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.TextView; public class NavDrawerListAdapter extends BaseAdapter { private Context context; private ArrayList<NavDrawerItem> navDrawerItems; public NavDrawerListAdapter(Context context, ArrayList<NavDrawerItem> navDrawerItems) { this.context = context; this.navDrawerItems = navDrawerItems; } @Override public int getCount() { return navDrawerItems.size(); } @Override public Object getItem(int position) { return navDrawerItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater mInflater = (LayoutInflater) context .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); convertView = mInflater.inflate(R.layout.drawer_list_item, null); } TextView txtTitle = (TextView) convertView.findViewById(R.id.title); txtTitle.setText(navDrawerItems.get(position).getTitle()); return convertView; } }
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.
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.
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.
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.
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.
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
Its Awsome <3 🙂
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
wrong video demo? 🙂
Thanks. Let me check.
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;
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
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.
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
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.
Ok 🙂
How can i remove the horizontal scroll view and fit full image on the screen. even if is scaled so it fits.
Thanks.
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
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”.
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
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?
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 ?
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.
Thanks for your kind reply.. Kindly suggest what can i do further for the same please if you can
Hi ravi please drop sample code for supporting multiple screens in andoird
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
Hi Ravi. why it takes more time to display the image though using image loader?
I guess because of image size. All the images are of 1 MB approx.
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.
Thanks Hoangdata for your valuable tip.
Please help me
start load 10 picture and i click load then load 10 pic next
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?
You must place “android:name=.app.AppController” in in AndroidManifest.xml to load app controller before run application
Oh, it works! Thank you!
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…
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
Hello Ravi Sir,
How to add different image icon to navigation drawer..??
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
same problem with mine
Did you find out any solution ?
Even I got the same problem. The album appeared once the device got restarted.
is there any way we can refresh a gallery without rebooting a device?
(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.
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.
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.
wallpaper not scrolling in kitkat v4.4.4..please help
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
Ravi Sir i need your help really fast ..thanx
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
Ravi Sir can you please help me..can i expect any help from your side????????
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
Check your Eclipse LogCat for crash report.
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
Does your layout file contains the elements whatever I have for FullScreenViewActivity ?
i have double checked FullScreenViewActivity …..not able to find any error!
any other solution?
I was facing a same issue.. I tried with a new eclipse and its solved 🙂
you created the same project in eclipse different version? i will try that….. any other modifications?
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 ??
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
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.
Hi Moktar, I am glad that you find if very useful 🙂
@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
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 ?
I am not sure.
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
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 :).
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
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;
}
}
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
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
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?
i want the playstore link of your app
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?
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
Hi ravi , i want to know how to grab wallpapers from server location and not to use galleries from picasa.
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.
where is the btn_rounded_corner
Download The code from this page and you will find it in the folder.
@Nishant are you talking about res code or project code as I cant find the project code and res folder does not have it
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
change the username in AppConst class
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?
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
great tutorial. but how can i swipe left right to the next previous images in my picasa album
i want to crop image before setting wallpaper ..please help
hi
use edmodo crop library
can you give me the code to crop images and set wallpaper
Source code is not Downloading
Plz Do something
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.
tnx alex i use your code
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
They will load, but it will take sometime due to cache validation.
Is there anyway i could speed the process? like for example only load like the first 20 pictures or any other solution?
Never mind Ravi, I forgot to un-comment some lines of code.
Ok.
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.
How to remove settings screen?
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 🙂
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 😀
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??
solved this the other day but cant remember how i solved it.
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?
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”;
IS this for re-sizing on device?
No this ony fetches a smaller version of the image from picasa.
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..
I think it is I am working on something with pinch zoom I let you know if i get it to work.
Hey Michael! Did you get pinch zoom to work? I want it in my app so would be very helpful! 🙂
Sorry got stuck in other dev projects, so didn’t look further into it