com.tapcentive.sdk.icons.IconRetrievalService.java Source code

Java tutorial

Introduction

Here is the source code for com.tapcentive.sdk.icons.IconRetrievalService.java

Source

/*
 * Copyright 2015 Tapcentive, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.tapcentive.sdk.icons;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

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

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.VolleyError;
import com.android.volley.Request.Method;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.Volley;
import com.tapcentive.sdk.TapcentiveLibrary;
import com.tapcentive.sdk.service.util.CustomJsonObjectRequest;
import com.tapcentive.sdk.touchpoint.nfc.PrefsProfileStorage;

import android.annotation.SuppressLint;
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import android.webkit.MimeTypeMap;

public class IconRetrievalService extends IntentService {
    public final String TAG = "ICON_RETRIEVAL_SERVICE";
    public static String ICONDIR = "icondir";
    private static RequestQueue requestQueue = null;

    public IconRetrievalService() {
        super("IconRetrievalService");

    }

    synchronized RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            requestQueue = Volley.newRequestQueue(getApplicationContext());
        }
        return requestQueue;
    }

    class IconReference {
        public long id;
        public String url;

        public IconReference(long id, String url) {
            this.id = id;
            this.url = url;
        }
    }

    class CustomIconRequest extends Request<File> {
        IconReference icon;
        Map<String, String> headers;

        CustomIconRequest(IconReference icon, ErrorListener listener, Map<String, String> headers) {
            super(Request.Method.GET, icon.url, listener);
            this.icon = icon;
            this.headers = headers;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            return headers;
        }

        @SuppressLint("DefaultLocale")
        @Override
        protected Response<File> parseNetworkResponse(NetworkResponse response) {
            Log.d(TAG, "Got a response reading response to icon: " + icon.toString());
            String contentType = "";
            for (String key : response.headers.keySet()) {
                if (key.toLowerCase().equals("content-type")) {
                    contentType = response.headers.get(key);
                    break;
                }
            }

            MimeTypeMap mimeMap = MimeTypeMap.getSingleton();
            String extension = mimeMap.getExtensionFromMimeType(contentType);
            if (extension.equals("jpeg")) {
                extension = "jpg";
            }

            response.headers.get("content-type");
            File newIconFile = new File(getApplicationContext().getFilesDir() + "/" + ICONDIR + "/"
                    + Long.toString(icon.id) + "." + extension);
            try {
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newIconFile));
                bos.write(response.data, 0, response.data.length);
                bos.close();
                Log.d(TAG, "Successfully retrieved icon: " + icon.toString());
                return Response.success(newIconFile, HttpHeaderParser.parseCacheHeaders(response));
            } catch (FileNotFoundException e) {
                Log.d(TAG, "File Not Found Exception: " + e.toString());
                return Response.error(new VolleyError(e));
            } catch (IOException e) {
                Log.d(TAG, "IO Exception: " + e.toString());
                return Response.error(new VolleyError(e));
            }
        }

        @Override
        protected void deliverResponse(File response) {
            // Do nothing for now
        }
    }

    protected void retrieveIcon(IconReference icon) {
        // Check to see if we have this icon

        // If we don't have this icon
        Log.d(TAG, "Attempting to fetch custom icon: " + icon.toString());

        Map<String, String> headers = new HashMap<String, String>();

        try {
            final RequestQueue queue = this.getRequestQueue();

            CustomIconRequest iconRequest = new CustomIconRequest(icon, new ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.d(TAG, error.toString());
                }
            }, headers);
            iconRequest.getHeaders().put("User-Agent", "consumer");
            // Add the request to the queue and execute
            queue.add(iconRequest);
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "Exception" + e.toString());
        }
    }

    protected void syncIcons(List<IconReference> icon_list) {
        Log.d(TAG, "Calling syncIcons with icon_list: " + icon_list.toString());
        // Get the current list of stored icons and delete ones that aren't in the icon_list
        File dir = new File(getApplicationContext().getFilesDir() + "/" + ICONDIR);
        dir.mkdirs(); // Just make sure it exists always
        LinkedList<Long> localFileIds = new LinkedList<Long>();
        if (dir.isDirectory()) {
            for (final File iconFile : dir.listFiles()) {
                //String iconFileId = iconFile.getName().substring(0, iconFile.getName().length()-4); // Remove .png, .gif, etc
                String iconFileId = iconFile.getName().substring(0, iconFile.getName().lastIndexOf(".")); // Remove extension
                localFileIds.add(Long.parseLong(iconFileId));
                boolean found = false;
                for (IconReference ref : icon_list) {
                    if (Long.toString(ref.id).equals(iconFileId)) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    iconFile.delete();
                }
            }
            Log.d(TAG, "Would start to sync icons here: " + icon_list.toString());
            for (IconReference icon : icon_list) {
                if (!localFileIds.contains(icon.id)) {
                    retrieveIcon(icon);
                }
            }
        }

    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "Called IconRetrievalService::onHandleIntent");
        // Get client profile token
        // XXX: Is it really safe to assume we have a valid client token? 
        getList(new ListCallback() {
            public void gotList(JSONObject result) {
                LinkedList<IconReference> icon_list = new LinkedList<IconReference>();
                try {
                    Log.d(TAG, result.toString());
                    JSONArray icons = result.getJSONArray("icon_list");
                    for (int i = 0; i < icons.length(); i++) {
                        JSONObject icon = icons.getJSONObject(i);
                        icon_list.add(new IconReference(icon.getLong("id"), icon.getString("url")));
                    }
                    syncIcons(icon_list);
                } catch (Exception e) {
                    // XXX: What to do? 
                    Log.d(TAG, "Problem getting icons list: " + e.toString());
                }

            };

            public void gotError() {
                Log.d(TAG, "Got an error in IRS list retrieval");
            };
        });
    }

    interface ListCallback {
        public void gotList(JSONObject result);

        public void gotError();
    }

    private void getList(final ListCallback callback) {
        PrefsProfileStorage prefStorage = new PrefsProfileStorage(getApplicationContext());
        String consumerTemplate = prefStorage.getProfile();
        Log.d(TAG, "Last profile fetch attempt: " + prefStorage.getLastAccessTime());
        if (consumerTemplate == null) {
            Log.d(TAG, "No consumer template, skipping icon list retrieval");
            // Haven't registered consumer template?
            return;
        }

        Map<String, String> headers = new HashMap<String, String>();
        JSONObject jsonTemplate = new JSONObject();

        try {
            headers.put("User-Agent", "consumer");

            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            String msiURLString = sharedPref.getString("pref_key_msi_url", "");
            if ((msiURLString != null) && (!msiURLString.equals(""))) {
                String url = msiURLString + "/icon/list";
                jsonTemplate.put("template", consumerTemplate);

                final RequestQueue queue = this.getRequestQueue();

                CustomJsonObjectRequest jsonRequest = new CustomJsonObjectRequest(Method.POST, url, jsonTemplate,
                        new Response.Listener<JSONObject>() {
                            @Override
                            public void onResponse(JSONObject response) {
                                callback.gotList(response);
                            }
                        }, new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Log.d(TAG, "Error" + error.toString());
                                if (error == null || error.networkResponse == null) {
                                    callback.gotError();
                                    return;
                                }
                                if (error.networkResponse.statusCode == 400
                                        || error.networkResponse.statusCode == 204
                                        || error.networkResponse.statusCode == 403) {
                                    callback.gotError();
                                    return;
                                }
                            }
                        }, headers);

                // Add the request to the queue and execute
                queue.add(jsonRequest);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, "Exception" + e.toString());
            callback.gotError();
        }
    }

}