Working on vocabulary management from PCB

parent 3e0c1d65
......@@ -70,5 +70,6 @@ dependencies {
compile 'com.github.nkzawa:socket.io-client:0.5.0'
compile 'com.koushikdutta.async:androidasync:2.+'
compile 'com.android.support:support-v4:21.0.+'
compile 'com.koushikdutta.ion:ion:2.+' //required for upload images
}
......@@ -66,14 +66,15 @@ public class UploadActivity extends Activity {
if (e == null)
Log.i(this.getClass().getCanonicalName(), " Uploaded to " + context.getResources().getString(R.string.server) + " " + result);
else
Log.e(this.getClass().getCanonicalName(), "error uploading");
Log.e(this.getClass().getCanonicalName(), "Upload error:" + e.getMessage());
if (result != null)
Log.i(this.getClass().getCanonicalName(), result.toString());
Log.i(this.getClass().getCanonicalName(), "Upload result:" + result.toString());
else
Log.i(this.getClass().getCanonicalName(), "no result");
}
});
ion.dump();
Log.i(this.getClass().getCanonicalName(), " Uploading 3 ");
ion.dump();
}
}
......@@ -23,7 +23,8 @@ import java.util.LinkedList;
* @see Room
*/
public class Action {
private String type;
protected String type;
/**
* It creates an action for any user, both online and offline actions.
......
......@@ -23,10 +23,6 @@ import java.util.LinkedList;
* @see Room
*/
public class PictoAction extends Action {
private String type;
private String timestamp;
private int id_sup;
private int id_stu;
private Picto picto;
private float gps_lat;
private float gps_lon;
......@@ -48,7 +44,7 @@ public class PictoAction extends Action {
super(type);
this.picto=picto;
}
@Override
public JSONObject get_json(){
final String param_picto="picto";
try {
......
......@@ -23,10 +23,6 @@ import java.util.LinkedList;
* @see Room
*/
public class PictosAction extends Action {
private String type;
private String timestamp;
private int id_sup;
private int id_stu;
LinkedList<Picto> pictos;
private float gps_lat;
private float gps_lon;
......@@ -45,7 +41,7 @@ public class PictosAction extends Action {
this.pictos=pictos;
}
@Override
public JSONObject get_json() {
final String param_pictos="pictos";
try{
......
package com.yottacode.pictogram.action;
import android.util.Log;
import com.yottacode.pictogram.dao.Picto;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException;
import org.json.JSONObject;
/**
* The vocabulary is modified from the PCB by a supervisor for a given student
* @author Fernando Martinez Santiago
* @version 1.0
* @see Room
*/
public class VocabularyAction extends Action {
Picto picto;
//Picto Action types
public static final String ADD="Vocabulay_Add";
public static final String DELETE="Vocabulay_Delete";
public static final String DISABLE="Vocabulay_Disable";
public static final String ENABLE="Vocabulay_Enable";
/**
* It creates an action for any user regarding a picto, both online and offline actions.
*
* @param type
* @param picto
*/
public VocabularyAction(String type, Picto picto){
super(type);
this.picto=picto;
}
@Override
public JSONObject get_json(){
final String param_picto="picto";
try {
return super.get_json().put(param_picto, this.get_json_picto());
}catch(JSONException e) {
Log.e(this.getClass().getCanonicalName(),e.getLocalizedMessage());
return null;
}
}
public JSONObject get_json_picto() throws JSONException {
final String param_id_json="id";
final String param_picto="picto";
final String param_expression="expression";
final String param_expr_lang="lang";
final String param_expr_text="text";
final String param_attrs="attributes";
final String param_picto_id="id";
final String param_picto_uri="uri";
final String param_picto_cat="category";
JSONObject subsubPicto = new JSONObject().put(param_picto_id, picto.get_id())
.put(param_picto_uri, picto.get_url())
.put(param_picto_cat, picto.get_category());
JSONObject attributes = new JSONObject(picto.get_json_attrs());
JSONObject expression = new JSONObject().put(param_expr_lang,PCBcontext.getPcbdb().getCurrentUser().get_lang_stu())
.put(param_expr_text,picto.get_translation());
JSONObject subPicto = new JSONObject().put(param_id_json, 1470)
.put(param_picto, subsubPicto)
.put(param_expression,expression)
.put(param_attrs, attributes);
return subPicto;
}
}
\ No newline at end of file
......@@ -14,10 +14,9 @@ import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Vector;
import com.yottacode.pictogram.action.Action;
import com.yottacode.pictogram.tools.Img;
import com.yottacode.pictogram.net.ImgDownloader;
import com.yottacode.pictogram.net.iImgDownloaderListener;
......@@ -26,7 +25,7 @@ import org.json.JSONException;
/**
* Data Access Object to manage Pictogram Communicator Board database
* Data Access Object to manage Pictogram Communicator Board database regarding App information that is not user-dependent
* This class requires:
* The script to create the DB allocated in res/raw/pcbdb_create.sql
* The entries db_name and db_script_error in strings.xml
......@@ -287,7 +286,7 @@ public class Device extends SQLiteOpenHelper {
* @see com.yottacode.pictogram.dao.PCBDBHelper
*/
public void synchronizeUsers(Vector<User> users, iImgDownloaderListener imgListener) throws JSONException {
Log.d("LoginActivity", "1:" + new SimpleDateFormat("HH:mm:ss"));
Vector<User> prev_users = getUsers();
Vector<Img> imgs = new Vector<Img>(users.size() * 2);
......@@ -306,11 +305,12 @@ public class Device extends SQLiteOpenHelper {
}
for (User user : prev_users)
db.execSQL("DELETE FROM users_detail WHERE id_stu=" + user.get_id_stu() + " AND id_sup=" + user.get_id_sup());
db.delete("users_detail","id_stu=? AND id_sup=?",new String[]{Integer.toString(user.get_id_stu()),Integer.toString(user.get_id_sup())});
ImgDownloader downloader = new ImgDownloader(this.context, imgListener);
ImgDownloader downloader = new ImgDownloader(this.context, imgListener, ImgDownloader.source.remote );
downloader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,imgs);
db.close();
}
......@@ -374,6 +374,24 @@ public class Device extends SQLiteOpenHelper {
db.close();
return path;
}
/**
* get the next local id for a new local pictogram
*
* @see com.yottacode.pictogram.dao.Picto
*/
public int getNextLocalPictoID() {
SQLiteDatabase db = this.getReadableDatabase();
int next_key;
Cursor cursor = db.query("picto", new String[]{"MIN(id)"}, null, null, null, null, null, "1");
cursor.moveToFirst();
next_key=cursor.getInt(1)-1;
cursor.close();
db.close();
return next_key;
}
@Override
public void onCreate(SQLiteDatabase db) throws RuntimeException {
......
......@@ -26,6 +26,7 @@ import org.json.JSONObject;
/**
* Platform abstraction (Android)
* @see PCBDBHelper
* *
*
* @author Fernando Martinez Santiago
......@@ -50,7 +51,7 @@ class DeviceHelper {
}
/**
* Data Access Object to manage Pictogram Communicator Board database
* Data Access Object to manage Pictogram Communicator Board database regarding a logged user
* This class requires:
* The script to create the DB allocated in res/raw/pcbdb_create.sql
* The entries db_name and db_script_error in strings.xml
......@@ -132,7 +133,7 @@ public class PCBDBHelper extends SQLiteOpenHelper {
public void insertAction(Action action) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values=new ContentValues(1);
values.put("json_action",action.getDescription().toString());
values.put("json_action", action.getDescription().toString());
db.insert("action", null, values);
db.close();
}
......@@ -188,6 +189,9 @@ public class PCBDBHelper extends SQLiteOpenHelper {
return vocabulary;
}
/**
* Set/update the set of pictos of the current student. Pictos which are no longer used are dropped from the DB
*
......@@ -242,7 +246,11 @@ public class PCBDBHelper extends SQLiteOpenHelper {
public void deletePicto(int picto_id) {
int id_stu = this.getCurrentUser().get_id_stu();
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DELETE FROM collection WHERE id_stu=" + id_stu + " AND id_picto=" + picto_id);
db.delete("collection","id_stu=? AND id_sup=? AND id_picto=?",
new String[]{ Integer.toString(this.currentUser.get_id_stu()),
Integer.toString(this.currentUser.get_id_sup()),
Integer.toString(picto_id)});
db.close();
}
/**
......
......@@ -39,7 +39,9 @@ public class Picto extends Img {
private JSONObject attributes;
private String translation;
public Picto(int id, String translation, int cat, int column, int row) throws JSONException {
this(id, null, translation, new JSONObject().put(JSON_ATTTRS.CATEGORY,cat).put(JSON_ATTTRS.COLUMN,column).put(JSON_ATTTRS.ROW,row));
}
public Picto(int id, String url,String translation, String attributes) throws JSONException {
this(id, url, translation, new JSONObject(attributes));
}
......
......@@ -4,8 +4,12 @@ import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import com.google.gson.JsonObject;
import com.yottacode.pictogram.dao.PCBDBHelper;
import com.yottacode.pictogram.dao.Picto;
import com.yottacode.pictogram.net.ImgDownloader;
import com.yottacode.pictogram.net.ImgUploader;
import com.yottacode.pictogram.net.iImgUploaderListener;
import com.yottacode.pictogram.tools.Img;
import com.yottacode.net.iRestapiListener;
import com.yottacode.pictogram.action.Room;
......@@ -20,7 +24,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Hashtable;
import java.util.InputMismatchException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
......@@ -81,7 +87,7 @@ public class Vocabulary implements Iterable<Picto> {
String uri=args.getJSONObject("picto").getString("uri");
JSONObject attrs_picto = args.getJSONObject("attributes");
addPicto(new Picto(picto_id, uri, text, attrs_picto));
addPicto(new Picto(picto_id, uri, text, attrs_picto),ImgDownloader.source.remote);
} catch (JSONException e) {
Log.e(this.getClass().getCanonicalName(), e.getClass().getCanonicalName() + "--" + e);
......@@ -162,7 +168,6 @@ public class Vocabulary implements Iterable<Picto> {
Vector<Img> imgs=new Vector<Img>(updated_collection.length);
this.pictos.clear();
for (Picto updated_picto: updated_collection) {
LinkedList<Picto> pictos_cat;
......@@ -180,43 +185,118 @@ public class Vocabulary implements Iterable<Picto> {
imgs.add(new Img(picto.get_id(), picto.get_url(), Img.VOCABULARY));
}
Log.d(this.getClass().getName(), "Vocabulary size: " + updated_collection.length);
ImgDownloader downloader = new ImgDownloader(PCBcontext.getContext(), imgListener);
ImgDownloader downloader = new ImgDownloader(PCBcontext.getContext(), imgListener,ImgDownloader.source.remote);
downloader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imgs);
PCBcontext.getPcbdb().setStudentVocabulary(this);
}
public int size() { return this.pictos.size();}
/**
* It includes/updates a new picto to the user collection: download de image, add the picto to the current vocabulary and update the database
* It includes/updates a new picto to the user collection: download the image from remote or local storage, add the picto to the current vocabulary and update the database
* @param pic
*/
public void addPicto(Picto pic){
public void addPicto(Picto pic, ImgDownloader.source source){
Vector<Img> imgs=new Vector<Img>(1);
imgs.add(new Img(pic.get_id(), pic.get_url(), Img.VOCABULARY));
ImgDownloader downloader = new ImgDownloader(PCBcontext.getContext(), imgListener);
ImgDownloader downloader = new ImgDownloader(PCBcontext.getContext(), imgListener,source);
downloader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imgs);
loadPicto(pic);
PCBcontext.getPcbdb().addPicto(pic);
}
/*
* It saves locally a new picto obtained from the PCB
*/
public void savePicto(String exp, int cat, int coord_x, int coord_y) {
int id=PCBcontext.getDevice().getNextLocalPictoID();
try {
Picto picto = new Picto(id, exp, cat, coord_x, coord_y);
addPicto(picto, ImgDownloader.source.local);
} catch (JSONException e) {
e.printStackTrace();
Log.e(Vocabulary.class.getCanonicalName(),e.getMessage());
}
}
/**
*TODO: to be finished and tried
*/
public void uploadPicto(String path, String name, String exp, int cat, int coord_x, int coord_y) throws IOException {
File file = new File(path);
*TODO: Upload a local picto. It requires: i) to upload the image, ii) to upload the expression and iii) to include the picto to the current student vocabulary
*
**/
public void uploadPicto(final Picto picto) throws IOException {
File file = picto.file(PCBcontext.getContext());
FileInputStream imageInFile = new FileInputStream(file);
byte imageData[] = new byte[(int)file.length()];
imageInFile.read(imageData);
Hashtable<String,String> params=new Hashtable<>(3);
params.put("filename", name);
params.put("folder", "custompictos");
params.put("id", String.valueOf(PCBcontext.getPcbdb().getCurrentUser().get_id_stu()));
params.put("file", String.valueOf(imageData));
PCBcontext.getRestapiWrapper().ask("upload", params, "post", null);
final Hashtable<String,String> params=new Hashtable<>(3);
ImgUploader uploader= new ImgUploader(PCBcontext.getContext());
uploader.upload(picto, new iImgUploaderListener() {
@Override
public void complete(JsonObject result) {
Log.d(this.getClass().getCanonicalName(), "Uploaded img result: " + result.getAsString());
Hashtable<String, String> params=new Hashtable<String, String>(3);
params.put("id_cat",Integer.toString(picto.get_category()));
params.put("coord_x",Integer.toString(picto.get_column()));
params.put("coord_y",Integer.toString(picto.get_row()));
PCBcontext.getRestapiWrapper().ask("stu/"+PCBcontext.getPcbdb().getCurrentUser().get_id_stu()+"/picto", params, "post", new iRestapiListener() {
@Override
public void preExecute() {
}
@Override
public void result(JSONArray result) {
}
@Override
public void result(JSONObject result) {
Log.d(this.getClass().getCanonicalName(), "Uploaded picto result: " + result.toString());
int remoteid_picto=0;
Hashtable<String, String> params=new Hashtable<String, String>(3);
params.put("picto",Integer.toString(remoteid_picto));
params.put("lang",PCBcontext.getPcbdb().getCurrentUser().get_lang_stu());
params.put("text", picto.get_translation());
PCBcontext.getRestapiWrapper().ask("picto/exp", params, "post", new iRestapiListener() {
@Override
public void preExecute() {
}
@Override
public void result(JSONArray result) {
}
@Override
public void result(JSONObject result) {
PCBcontext.getPcbdb().deletePicto(picto.get_id());
}
@Override
public void error(Exception e) {
}
});
}
@Override
public void error(Exception e) {
}
});
}
@Override
public void error(Exception e, int http_code) {
Log.e("Upload", "Error: " + e.getLocalizedMessage() + " HTTP code:" + http_code);
for (StackTraceElement s : e.getStackTrace())
Log.e("Upload", s.toString());
}
});
}
/**
......
......@@ -9,6 +9,8 @@ import android.util.Log;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.tools.Img;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
......@@ -18,7 +20,7 @@ import java.util.Calendar;
import java.util.Vector;
/**
* Image downloader from the server for pictograms and student's and supervisor's profile pictures.
* Image downloader from the server or local for pictograms and student's and supervisor's profile pictures.
* Permissions required in AndroidManifest.xml:
* <uses-permission android:name="android.permission.INTERNET" />
......@@ -27,25 +29,27 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
iImgDownloaderListener imgListener;
public static enum status {downloading, downloaded_ok, downloaded_failed}
public static enum source{remote,local}
public status current;
private boolean force_download;
Context context;
ActivityManager.MemoryInfo mi;
ActivityManager activityManager;
source source;
public ImgDownloader(Context context, iImgDownloaderListener listener) {
public ImgDownloader(Context context, iImgDownloaderListener listener, source source) {
this.imgListener = listener;
this.context=context;
this.mi = new ActivityManager.MemoryInfo();
this.activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
this.force_download=context.getResources().getBoolean(R.bool.force_img_download);
this.source=source;
}
@Override
protected void onPreExecute() {
Log.d(this.getClass().getCanonicalName(), "Pre-EXEC");
}
protected Img doInBackground( Vector<Img> imgs) {
......@@ -59,24 +63,27 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
int seconds = Calendar.getInstance().get(Calendar.SECOND);
try {
String surl=null;
for (Img img: imgs) {
if (!img.exists_bitmap(this.context) || this.force_download) try {
surl=context.getResources().getString(R.string.server)+"/"+img.get_url();
this.activityManager.getMemoryInfo(mi);
URL url = new URL(surl);
URLConnection ucon = url.openConnection();
is = ucon.getInputStream();
if (this.source==source.remote) {
String surl = context.getResources().getString(R.string.server) + "/" + img.get_url();
URL url = new URL(surl);
URLConnection ucon = url.openConnection();
is = ucon.getInputStream();
}else {
File file=new File(img.get_url());
is=new FileInputStream(file);
}
int size=img.save_bitmap(this.context, is);
allsize+=size;
i++;
} catch (IOException e) {
j++;
Log.e(this.getClass().getCanonicalName(), surl + " was not downloaded: "+e);
Log.e(this.getClass().getCanonicalName(), img.get_url() + " was not downloaded: "+e);
} finally {
if (is != null) is.close();
}
......@@ -88,7 +95,7 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
}
seconds=Calendar.getInstance().get(Calendar.SECOND)-seconds;
Log.i(this.getClass().getCanonicalName(),
"LoginActivity: Downloaded: " + i+"/"+imgs.size()+ " (size:"+allsize/1024+" Kbytes)"+
"Images Downloaded: " + i+"/"+imgs.size()+ " (size:"+allsize/1024+" Kbytes)"+
". Cached: "+ (imgs.size()-i)+"/"+imgs.size()+
". Download failed: "+ j+"/"+imgs.size()+
". Memory required:"+((mi.availMem / 1048576L)-availableMegs)+" MB"+
......@@ -106,7 +113,7 @@ public class ImgDownloader extends AsyncTask<Vector<Img>, Void, Img> {
@Override
protected void onPostExecute(Img img) {
Log.d(this.getClass().getCanonicalName(), "LoginActivity: Inside OnPostExecute()"+new SimpleDateFormat("HH:mm:ss"));
Log.d(this.getClass().getCanonicalName(), "Inside OnPostExecute()"+new SimpleDateFormat("HH:mm:ss"));
if (imgListener!=null)
if(img == null) imgListener.loadComplete();
else imgListener.loadImg(img);
......
package com.yottacode.pictogram.net;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutionException;
import com.google.gson.JsonObject;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import com.koushikdutta.ion.Response;
import com.yottacode.net.SSLDummyContext;
import com.yottacode.pictogram.R;
import com.yottacode.pictogram.tools.Img;
import com.yottacode.pictogram.tools.PCBcontext;
import android.content.Context;
import android.util.Log;
/**
* Image downloader from the server for pictograms and student's and supervisor's profile pictures.
* Permissions required in AndroidManifest.xml:
* <uses-permission android:name="android.permission.INTERNET" />
*/
public class ImgUploader {
iImgUploaderListener imgListener;
Context context;
public ImgUploader(Context context) {
this.context=context;
}
public void upload( Img img, final iImgUploaderListener listener) throws UnsupportedEncodingException {
if (!img.get_filetype().equalsIgnoreCase("png"))
throw new UnsupportedEncodingException("Extension "+img.get_filetype()+" is not supported. Only png files");
Ion ion = Ion.getDefault(context);
Log.i(this.getClass().getCanonicalName(), "Uploading " + img.file_name()+"."+img.get_type());
File file = new File(img.file_name());
Response<JsonObject> response=null;
try {
response=ion.with(context)
.load("POST", context.getResources().getString(R.string.server) + "/picto/upload")
.setMultipartParameter("filename", Integer.toString(img.get_id()))
.setMultipartParameter("extension", img.get_filetype())
.setMultipartParameter("owner", Integer.toString(PCBcontext.getPcbdb().getCurrentUser().get_id_sup()))
.setMultipartParameter("folder", "custompictos")
.setMultipartParameter("source", "2")
.setMultipartParameter("token", PCBcontext.getRestapiWrapper().getToken())
.setMultipartFile("file", "image/png", file)
.asJsonObject()
.withResponse().get();
if (response != null && response.getHeaders().code() == 200) {
JsonObject result = response.getResult();
Log.i(this.getClass().getCanonicalName(), "Image uploaded:"+result.getAsString());
listener.complete(result);
} else {
Log.i(this.getClass().getCanonicalName(), "Image upload failed ");
if (response != null)
Log.e(this.getClass().getCanonicalName(), "Image upload response: " + response.getHeaders());
listener.error(new Exception("ImgUploader error when upload "+img.get_url()), response == null ? -1 : response.getHeaders().code());
}
} catch (InterruptedException e) {
Log.e(this.getClass().getCanonicalName(), "Image upload error: " + e.getMessage());
listener.error(e, response == null ? -1 : response.getHeaders().code());
} catch (ExecutionException e) {
Log.e(this.getClass().getCanonicalName(), "Image upload error: " + e.getMessage());
listener.error(e, response == null ? -1 : response.getHeaders().code());
}
ion.dump();
}
}
package com.yottacode.pictogram.net;
import com.google.gson.JsonObject;
/**
* Created by Fernando on 26/02/16.
*/
public interface iImgUploaderListener {
public void complete(JsonObject result);
public void error(Exception e, int http_code);
}
......@@ -34,13 +34,14 @@ public class Img {
protected int id;
protected String url;
String type;
final static String FILETYPE="png";
Bitmap bitmap;
/**
*
* @param id
* @param url
* @param type is Vocabuylary, Student or Supervisor
* @param type is Vocabulary, Student or Supervisor
*/
public Img(int id, String url, String type) {
this.id = id;
......@@ -48,11 +49,12 @@ public class Img {
this.type=type;
this.bitmap=null;
}
public String file_name() { return this.id+".png"; }
public String file_name() { return this.id+Img.FILETYPE; }
public int get_id() { return this.id;}
public String get_url() { return this.url;}
public String get_type() { return this.type;}
public String get_filetype() { return Img.FILETYPE;}
/**
* Load if necessary the bitmap from disk, and it is returned. IIf it is not available, return null
......@@ -62,7 +64,7 @@ public class Img {
*/
public Bitmap get_bitmap(Context context) throws IOException {
if (this.bitmap==null) {
File file = file(context, this.type);
File file = file(context);
if (file.exists()) {
FileInputStream is = new FileInputStream(file);
this.bitmap = BitmapFactory.decodeStream(is);
......@@ -78,7 +80,7 @@ public class Img {
* @throws FileNotFoundException
*/
public void delete_bitmap(Context context) throws IOException {
File file = file(context, this.type);
File file = file(context);
file.delete();
}
......@@ -88,17 +90,22 @@ public class Img {
* @return true if the bitmap is locally stored
*/
public boolean exists_bitmap(Context context) {
return file(context, this.type).exists();
return file(context).exists();
}
private static String path(Context context, String type) {
public static String path(Context context, String type) {
String path = context.getFilesDir()+File.separator +"pictures" + File.separatorChar + type + File.separatorChar;
return path;
}
private File file(Context context, String type) {
/**
* The local file where the img is saved. It depends on the image type
* @param context
* @return
*/
public File file(Context context) {
String path=path(context, this.type);
return new File(path, file_name());
}
......@@ -110,7 +117,7 @@ public class Img {
*/
public int save_bitmap(Context context, InputStream is) throws IOException {
File file = file(context, this.type);
File file = file(context);
FileOutputStream os = new FileOutputStream(file);
try {
this.bitmap = BitmapFactory.decodeStream(is);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment