Search code examples
androidstorageinternalandroid-context

Context, storing internal memory and reading from it


Hello I have a problem with the context in the line productLookup(productId, Contexto), I can't get it right.

What I'm trying to do is when I get the data from the DB via web, with the objects I also want to pass the ID of the objects to the productLookup function to download the associated jpg and save it in the internal memory. Don't know if is the best why to do it. If you guys have any suggestions don't hesitate to let it me know it!.

package com.example.proyectoprueba;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

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

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

public class prueba extends ActionBarActivity{

 // DB Class to perform DB related operations
DBController controller = new DBController(this);
// Progress Dialog Object
ProgressDialog prgDialog;
HashMap<String, String> queryValues;

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

    ArrayList<HashMap<String, String>> platoList = controller.getAllPlatos();
    // If users exists in SQLite DB
    if (platoList.size() != 0) {
        // Set the User Array list in ListView
        ListAdapter adapter = new SimpleAdapter(prueba.this, platoList, R.layout.itemlista, new String[] {
                        "platoId", "platoNombre", "platoDescripcion", "platoPrecio" }, new int[] { R.id.codigo, R.id.nombre, R.id.descripcion, R.id.precio });
        ListView myList = (ListView) findViewById(R.id.listaplatos);
        myList.setAdapter(adapter);
    }

 // Initialize Progress Dialog properties
    prgDialog = new ProgressDialog(this);
    prgDialog.setMessage("Transferring Data from Remote MySQL DB and Syncing SQLite. Please wait...");
    prgDialog.setCancelable(false);

}

@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);
    return true;
}
public boolean onOptionsItemSelected(MenuItem item) {

    Intent intent;
    switch (item.getItemId()){
    case R.id.entremeses:
        intent =new Intent(this,prueba.class);
        this.startActivity(intent);
        break;
    case R.id.arrocesypasta:
        intent=new Intent(this,prueba.class);
        this.startActivity(intent);
        break;
    case R.id.bebidas:
        intent=new Intent(this,prueba.class);
        this.startActivity(intent);
        break;
    case R.id.refresh:
//              Transfer data from remote MySQL DB to SQLite on Android and perform Sync

          syncSQLiteMySQLDB();
          return true;

   } 


    return super.onOptionsItemSelected(item);
}



// Method to Sync MySQL to SQLite DB
public void syncSQLiteMySQLDB() {
    // Create AsycHttpClient object
    AsyncHttpClient client = new AsyncHttpClient();
    // Http Request Params Object
    RequestParams params = new RequestParams();
    // Show ProgressBar
    prgDialog.show();
    // Make Http call to getusers.php
    client.post("http://restaurantechinaimperial.com/mysqlsqlitesync/getplatos.php", params, new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(String response) {
                // Hide ProgressBar
                prgDialog.hide();
                // Update SQLite DB with response sent by getusers.php
                updateSQLite(response);
            }
            // When error occured
            @Override
            public void onFailure(int statusCode, Throwable error, String content) {
                // TODO Auto-generated method stub
                // Hide ProgressBar
                prgDialog.hide();
                if (statusCode == 404) {
                    Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
                } else if (statusCode == 500) {
                    Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",
                            Toast.LENGTH_LONG).show();
                }
            }
    });
}

public void updateSQLite(String response){
    ArrayList<HashMap<String, String>> platosynclist;
    platosynclist = new ArrayList<HashMap<String, String>>();
    // Create GSON object
    Gson gson = new GsonBuilder().create();
    try {
        // Extract JSON array from the response
        JSONArray arr = new JSONArray(response);
        System.out.println(arr.length());
        // If no of array elements is not zero
        if(arr.length() != 0){
            // Loop through each array element, get JSON object which has userid and username
            for (int i = 0; i < arr.length(); i++) {
                // Get JSON object
                JSONObject obj = (JSONObject) arr.get(i);
                System.out.println(obj.get("platoId"));
                System.out.println(obj.get("platoNombre"));
                System.out.println(obj.get("platoDescripcion"));
                System.out.println(obj.get("platoCategoria"));
                System.out.println(obj.get("platoCaracteristicas"));
                System.out.println(obj.get("platoPrecio"));
                // DB QueryValues Object to insert into SQLite
                queryValues = new HashMap<String, String>();
                // Add userID extracted from Object
                queryValues.put("platoId", obj.get("platoId").toString());
                // Add userName extracted from Object
                queryValues.put("platoNombre", obj.get("platoNombre").toString());
             // Add userID extracted from Object
                queryValues.put("platoDescripcion", obj.get("platoDescripcion").toString());
                // Add userName extracted from Object
                queryValues.put("platoCategoria", obj.get("platoCategoria").toString());
             // Add userID extracted from Object
                queryValues.put("platoCaracteristicas", obj.get("platoCaracteristicas").toString());
                // Add userName extracted from Object
                queryValues.put("platoPrecio", obj.get("platoPrecio").toString());
                // Insert Plato into SQLite DB
                controller.insertPlato(queryValues);
                HashMap<String, String> map = new HashMap<String, String>();
                // Add status for each plato in Hashmap
                map.put("Id", obj.get("platoId").toString());
                map.put("status", "1");
//I made the call here... it's right they why I did it?
                    platosynclist.add(map);
                    String productId=map.get("platoId");
                    try {
                        productLookup(productId);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }


        // Inform Remote MySQL DB about the completion of Sync activity by passing Sync status of Users
            updateMySQLSyncSts(gson.toJson(platosynclist));
            // Reload the Main Activity
            reloadActivity();
        }
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

// Method to inform remote MySQL DB about completion of Sync activity
public void updateMySQLSyncSts(String json) {
    System.out.println(json);
    AsyncHttpClient client = new AsyncHttpClient();
    RequestParams params = new RequestParams();
    params.put("syncsts", json);
    // Make Http call to updatesyncsts.php with JSON parameter which has Sync statuses of Users
    client.post("http://restaurantechinaimperial.com/mysqlsqlitesync/updatesyncstsplatos.php", params, new AsyncHttpResponseHandler() {
        @Override
        public void onSuccess(String response) {
            Toast.makeText(getApplicationContext(),    "MySQL DB has been informed about Sync activity", Toast.LENGTH_LONG).show();
        }

        @Override
        public void onFailure(int statusCode, Throwable error, String content) {
                Toast.makeText(getApplicationContext(), "Error Occured", Toast.LENGTH_LONG).show();
        }
    });
}

//download images

public String productLookup(String productID) throws IOException{


    URL url = new URL("http://www.restaurantechinaimperial.com/menufotos/" + productID + ".jpg");

    InputStream input = null;
    FileOutputStream output = null;

    try {
        String outputName = productID + "-thumbnail.jpg";

        input = url.openConnection().getInputStream();
        output = getApplicationContext().openFileOutput(outputName, Context.MODE_PRIVATE);

        int read;
        byte[] data = new byte[1024];
        while ((read = input.read(data)) != -1)
            output.write(data, 0, read);

        return outputName;

    } finally {
        if (output != null)
            output.close();
        if (input != null)
            input.close();
    }
}

public Bitmap decodeFile(File f){ 
    try { 
        //decode image size 
        BitmapFactory.Options o = new BitmapFactory.Options(); 
        o.inJustDecodeBounds = true; 
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);    
        int scale=1; 
        //decode with inSampleSize 
        BitmapFactory.Options o2 = new BitmapFactory.Options(); 
        o2.inSampleSize=scale; 
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
    } catch (FileNotFoundException e) {} 
    return null; 
}

My other question is to how to read the stored images, the add them in a dialog that I have in a list view. I think I have to use getFileStreamPath(filename); FileInputStream fi = new FileInputStream(filePath);

But not sure. There retrieve part from an other activity

   // If users exists in SQLite DB
        if (platoList.size() != 0) {
            // Set the User Array list in ListView
            final ListAdapter adapter = new SimpleAdapter(PlantillaChina.this, platoList, R.layout.itemlista, new String[] {
                            "platoId", "platoNombre", "platoDescripcion", "platoPrecio" }, new int[] {R.id.codigo, R.id.nombre, R.id.descripcion, R.id.precio });
            ListView myList = (ListView) findViewById(R.id.listaplatos);
            myList.setAdapter(adapter);
            myList.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int  
                                       position, long id) 
                {
                    HashMap<String, String> obj = (HashMap<String, String>) adapter.getItem(position);
                    String platoId=(String) obj.get("platoId");
                    String name = (String) obj.get("platoNombre");
                    String description= (String) obj.get("platoDescripcion");
                    final Dialog dialog = new Dialog(PlantillaChina.this);
                    dialog.setContentView(R.layout.platocompleto);
                    dialog.setTitle(name);
                    ImageView image=(ImageView) dialog.findViewById(R.id.imagen);

//                  image.setImageResource(R.drawable.ic_launcher);
                    String fname=new File(getFilesDir(),platoId +".jpg").getAbsolutePath();
                    Bitmap Imagen=BitmapFactory.decodeFile(fname);
                    image.setImageBitmap(Imagen);



                    TextView texto=(TextView) dialog.findViewById(R.id.descripcionCompleta);
                    texto.setText(description);
                    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.BLACK));
                    dialog.show();


                }

            });
        }
    }

NEW ERROR LOG

02-27 06:20:51.264: W/System.err(26443): java.io.FileNotFoundException: http://www.restaurantechinaimperial.com/menufotos/null.jpg
02-27 06:20:51.265: W/System.err(26443):    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
02-27 06:20:51.266: W/System.err(26443):    at com.example.proyectoprueba.prueba.productLookup(prueba.java:235)
02-27 06:20:51.266: W/System.err(26443):    at com.example.proyectoprueba.prueba.updateSQLite(prueba.java:186)
02-27 06:20:51.267: W/System.err(26443):    at com.example.proyectoprueba.prueba$1.onSuccess(prueba.java:122)
02-27 06:20:51.267: W/System.err(26443):    at com.loopj.android.http.AsyncHttpResponseHandler.onSuccess(AsyncHttpResponseHandler.java:232)
02-27 06:20:51.268: W/System.err(26443):    at com.loopj.android.http.AsyncHttpResponseHandler.onSuccess(AsyncHttpResponseHandler.java:220)
02-27 06:20:51.269: W/System.err(26443):    at com.loopj.android.http.AsyncHttpResponseHandler.onSuccess(AsyncHttpResponseHandler.java:245)
02-27 06:20:51.270: W/System.err(26443):    at com.loopj.android.http.AsyncHttpResponseHandler.handleMessage(AsyncHttpResponseHandler.java:365)
02-27 06:20:51.270: W/System.err(26443):    at com.loopj.android.http.AsyncHttpResponseHandler$ResponderHandler.handleMessage(AsyncHttpResponseHandler.java:135)
02-27 06:20:51.271: W/System.err(26443):    at android.os.Handler.dispatchMessage(Handler.java:110)
02-27 06:20:51.272: W/System.err(26443):    at android.os.Looper.loop(Looper.java:193)
02-27 06:20:51.272: W/System.err(26443):    at android.app.ActivityThread.main(ActivityThread.java:5323)
02-27 06:20:51.273: W/System.err(26443):    at java.lang.reflect.Method.invokeNative(Native Method)
02-27 06:20:51.274: W/System.err(26443):    at java.lang.reflect.Method.invoke(Method.java:515)
02-27 06:20:51.274: W/System.err(26443):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
02-27 06:20:51.275: W/System.err(26443):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
02-27 06:20:51.275: W/System.err(26443):    at dalvik.system.NativeStart.main(Native Method)

from this call inside the method updateSQLITE

 HashMap<String, String> map = new HashMap<String, String>();
                    // Add status for each plato in Hashmap
                    map.put("Id", obj.get("platoId").toString());
                    map.put("status", "1");
    //I made the call here... it's right they why I did it?
                        platosynclist.add(map);
                        String productId=map.get("platoId");
                        try {
                            productLookup(productId);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }

Solution

  • First put your big network dealing operation in AsynTask then then update your productLookup method as below

     public String productLookup(String productID) throws IOException{
    
        URL url = new URL("http://www.samplewebsite.com/" + productID + ".jpg");
    
        InputStream input = null;
        FileOutputStream output = null;
    
        try {
            String outputName = productID + "-thumbnail.jpg";
    
            input = url.openConnection().getInputStream();
            output = getApplicationContext().openFileOutput(outputName, Context.MODE_PRIVATE);
    
            int read;
            byte[] data = new byte[1024];
            while ((read = input.read(data)) != -1)
                output.write(data, 0, read);
    
            return outputName;
    
        } finally {
            if (output != null)
                output.close();
            if (input != null)
                input.close();
        }
    }
    

    Then call this method as

    try {
                productLookup(productId);
            } catch (IOException e) {
                e.printStackTrace();
            }
    

    Finally to read your saved file use the code given below

    private Bitmap decodeFile(File f){ 
            try { 
                //decode image size 
                BitmapFactory.Options o = new BitmapFactory.Options(); 
                o.inJustDecodeBounds = true; 
                BitmapFactory.decodeStream(new FileInputStream(f),null,o);    
                int scale=1; 
                //decode with inSampleSize 
                BitmapFactory.Options o2 = new BitmapFactory.Options(); 
                o2.inSampleSize=scale; 
                return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
            } catch (FileNotFoundException e) {} 
            return null; 
        } 
    

    Don't forget to add write external storage permission.

    Add below code in onCreate

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);
    

    To show image in dialog replace your code with enter code here

    Bitmap Imagen=decodeFile(new File(getFilesDir(),platoId +".jpg"));
                image.setImageBitmap(Imagen);