so for my android application i can insert an image to sqlite as a string. But im not sure exactly how i can retrieve this image from the database and convert it to a Image from string and display it in my app. Stuck for weeks, help appreciated! :(
Button Click saves image to sqlite
upload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Student student = new Student(profadmin.getText().toString());
student.setImageUri(ImageUri);
stud.updateImage(student);
Toast passes = Toast.makeText(ProfileActivity.this, "Profile Picture has been updated", Toast.LENGTH_SHORT);
passes.show();
}
});
Database Handler:
public int updateImage(Student student) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put(STUDENT_IMAGEURI, student.getImageUri().toString());
int rowsAffected = db.update(STUDENT_TABLE, values, STUDENT_ADMINNO + "=?", new String[]{String.valueOf(student.getAdminNo())});
db.close();
return rowsAffected;
}
Edit: Uploaded the image by clicking the empty ImageView (profileIV) , opening the android emulator gallery, choose image and then image will be displayed on the app. Then i click the 'Upload' button and it sends it to the database and uploads
public void onActivityResult(int reqCode,int resCode,Intent data){
if(resCode==RESULT_OK){
if(reqCode==1){
ImageUri = data.getData();
profileIV.setImageURI(data.getData());
}
}
What you can do is storing your pictures in your drawable folder.
Then you will just have to store the name in your database and retrieve the corresponding image thanks to this one. It will also allow you to avoid a heavy DB file.
Why you need to store image into database? it's not a good choice.
If you have to store image into database, you can encode you image with Base64,and store the result string into database. so you can decode the string to image. But this way will cause problems with large images.
I suggest you to store images with disk cache.
Related
I want to store a video in sqlite database. P.S. I do not want to store the path but the actual video contents.
I have converted the video in byte array and stored byte array in sqlite database. Upon retrieval bytearray is being converted into File. But video is not playing. Please help.
I want to store a video in sqlite database. P.S. I do not want to
store the path but the actual video contents.
Unless the videos are very short and take up little space (say up to 200k each, perhaps 1/10th of a second but would depend upon the format it is saved in) then you would likely encounter issues and exceptions/crashes.
Using a phone around 2 seconds of black took up 2.2Mb, 2 seconds of actually recording a video took up 7Mb.
Although SQLite has the ability to store relative large BLOB's as per :-
Maximum length of a string or BLOB
The maximum number of bytes in a string or BLOB in SQLite is defined
by the preprocessor macro SQLITE_MAX_LENGTH. The default value of this
macro is 1 billion (1 thousand million or 1,000,000,000). You can
raise or lower this value at compile-time using a command-line option
like this:
-DSQLITE_MAX_LENGTH=123456789 The current implementation will only support a string or BLOB length up to 231-1 or 2147483647. And some
built-in functions such as hex() might fail well before that point. In
security-sensitive applications it is best not to try to increase the
maximum string and blob length. In fact, you might do well to lower
the maximum string and blob length to something more in the range of a
few million if that is possible.
During part of SQLite's INSERT and SELECT processing, the complete
content of each row in the database is encoded as a single BLOB. So
the SQLITE_MAX_LENGTH parameter also determines the maximum number of
bytes in a row.
The maximum string or BLOB length can be lowered at run-time using the
sqlite3_limit(db,SQLITE_LIMIT_LENGTH,size) interface.
Limits In SQLite
The Android SDK's CursorWindow has a limitation of 2Mb and that is for all the columns of the row(s) if buffers. As such even if you can store Videos successfully, you may not be able to retrieve those Videos.
The recommended way is what you don't want, that is to store the path to the Video.
If i store the video in my internal/external storage and store the
path instead then how will i be able to access the same from some
other device.
You would have the same issue with the database as it's typically stored within the Applications data which is protected. That is unless the database is a pre-existing database (i.e. populated with data), in which case the database is distributed with the App via the APK.
If the latter, a pre-existing database distributed via the APK, then the videos can also be distributed as part of the APK and hence as protected as and as exposable as the database.
If your intention is to distribute videos between devices that are not part of the APK then SQlite is probably not the correct solution as it's an embedded database and has no client/server functionality built in.
Besides what if my device gets formatted then I will lose all the
data.
In such a scenario, the database would be as vulnerable as any other data, as that is all the database is, a file, just like a video, a word document etc which all need a suitable application to view/change the content. However, if the database is a pre-existing database, then simply re-installing the App would restore the database and other files from the APK.
Working Example
This uses the Suggested/Recommended method assuming the videos are to be distributed with the APK.
Note Videos Courtesey of Sample Videos
After creating new project 4 videos were downloaded and copied into the res/raw folder (after creating the raw folder) as per :-
The Database Helper (subclass of SQLiteOpenHelper) was created for a 2 column table an with
- _id column (note named _id for use with SimpleCursorAdapter).
- video_path for storing the path/name of the video (not the full path but sufficient to be able to determine the path from the data stored)
- Note UNIQUE has been coded to stop duplicates being added.
With some basic method to allow rows to be added and deleted and for all rows to be extracted (via a Cursor for use with the SimpleCursorAdapter).
DBHelper.java
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "myvideos";
public static final int DBVERSION = 1;
public static final String TBL_VIDEO = "video";
public static final String COL_VIDEO_ID = BaseColumns._ID;
public static final String COL_VIDEO_PATH = "video_path";
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mDB = this.getWritableDatabase();
}
#Override
public void onCreate(SQLiteDatabase db) {
String crt_video_table = "CREATE TABLE IF NOT EXISTS " + TBL_VIDEO + "(" +
COL_VIDEO_ID + " INTEGER PRIMARY KEY," +
COL_VIDEO_PATH + " TEXT UNIQUE" +
")";
db.execSQL(crt_video_table);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addVideo(String path) {
ContentValues cv = new ContentValues();
cv.put(COL_VIDEO_PATH,path);
return mDB.insert(TBL_VIDEO,null,cv);
}
public Cursor getVideos() {
return mDB.query(TBL_VIDEO,null,null,null,null,null,null);
}
public int deleteVideoFromDB(long id) {
String whereclause = COL_VIDEO_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
return mDB.delete(TBL_VIDEO,whereclause,whereargs);
}
}
A pretty straigforward MainActivity.java (see comments)
public class MainActivity extends AppCompatActivity {
TextView mMyTextView;
ListView mVideoList;
VideoView mVideoViewer;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyTextView = this.findViewById(R.id.mytext);
mVideoList = this.findViewById(R.id.videolist);
mVideoViewer = this.findViewById(R.id.videoviewer);
mDBHlpr = new DBHelper(this);
addVideosFromRawResourceToDB();
}
#Override
protected void onDestroy() {
mCsr.close(); //<<<<<<<<<< clear up the Cursor
super.onDestroy();
}
#Override
protected void onResume() {
super.onResume();
manageListView(); //<<<<<<<<<< rebuild and redisplay the List of Videos (in case they have changed)
}
/**
* Setup or Refresh the ListView adding the OnItemClick and OnItemLongClick listeners
*/
private void manageListView() {
mCsr = mDBHlpr.getVideos();
// Not setup so set it up
if (mSCA == null) {
// Instantiate the SimpleCursorAdapter
mSCA = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1, // Use stock layout
mCsr, // The Cursor with the list of videos
new String[]{DBHelper.COL_VIDEO_PATH}, // the column (columns)
new int[]{android.R.id.text1}, // the view id(s) into which the column(s) data will be placed
0
);
mVideoList.setAdapter(mSCA); // Set the adpater for the ListView
/**
* Add The Long Click Listener (will delete the video row from the DB (NOT the video))
*/
mVideoList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
mDBHlpr.deleteVideoFromDB(id);
manageListView(); // <<<<<<<<<< refresh the ListView as data has changed
return true;
}
});
/**
* Play the respective video when the item is clicked
* Note Cursor should be at the correct position so data can be extracted directly from the Cursor
*/
mVideoList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setCurrentVideo(mCsr.getString(mCsr.getColumnIndex(DBHelper.COL_VIDEO_PATH)));
}
});
} else {
mSCA.swapCursor(mCsr); //<<<<<<<<<< apply the changed Cursor
}
}
/**
* Set the currrent video and play it
* #param path the path (resource name of the video)
*/
private void setCurrentVideo(String path) {
mVideoViewer.setVideoURI(
Uri.parse(
"android.resource://" + getPackageName() + "/" + String.valueOf(
getResources().getIdentifier(
path,
"raw",
getPackageName())
)
)
);
mVideoViewer.start();
}
/**
* Look at all the resources in the res/raw folder and add the to the DB (not if they are duplicates due to UNQIUE)
*/
private void addVideosFromRawResourceToDB() {
Field[] fields=R.raw.class.getFields();
for(int count=0; count < fields.length; count++){
Log.i("Raw Asset: ", fields[count].getName());
mDBHlpr.addVideo(fields[count].getName());
}
}
}
Results
When first started (nothing plays) :-
After long clicking the 1Mb video (deleting the DB entry) :-
After clicking A Video in the List :-
You can use this approach
When save the video, save it in app private storage folder.
Context.getFilesDir()
This will give you the path to the app storage in ..\Andorid\data\data\com.example.app
and it will be in internal storage.
Where com.example.app will be your application package id. You can make a new folder here like Videos then save videos in this folder. Save its path in the DB. Only your app can access to this folder. No any other app or device user can access this folder. So no one can edit or delete your files except your application.
Moreover if user reset mobile this data will be deleted as well as your database and maybe your app too in some cases. So no need to worry about it that your files will be deleted but database has still their path. If file deleted then DB deleted too as well but only when app Uninstall, device reset or SD card erase.
I hope you are good.
I'm developping an application that has to retrieve images from sqlite database, for each row I have one image (using obviously blob as a type), and I was wondering if I could not only add one image but a lot, without knowing how much images the user wants to add, for example: User1 wants to add 3 images to database. User2 5 images and so on. How can I store them? is there a kind of Blob[] or something? And if possible how can I choose more than one image from galery?
I'm not used to make posts in english so I hope I explained well ^^'.
Thank you.
Save the images in a list as base64 strings like:
String img1 = Base64.encode(value_of_image, Base64.DEFAULT);
.
.
.
String img25 = Base64.encode(value_of_image, Base64.DEFAULT);
List<String> imagesListActivity = new ArrayList();
imagesList.add(img1);
.
.
.
imagesList.add(img25);
and in your save method in helper class, you can do sth like:
public void saveImageList(List<String> images){
ContentValues cv = new ContentValues();
for(int i = 0; i < images.length; i++){
cv.put(COL_NAME, images[i);
}
}
and in activity class, try this by passing the actual list like below:
DBHelper dbHelper = new DBHelper();
dbHelper.saveImageList(imagesList);
I am new to android and I'm facing an issue while displaying image from server based its name from Sqlite
ie:
I stored only image name (text) in SQLite database (column name images) and I want to load images from Server based on the sqlite image name the image want to display in imageview
In server I create a folder like Cars in that folder I store images with car names..but in sqlite I just add a carname in text format with .jpeg
I have two column names in my DB:
first is Car name
Second is Car Detail
When user selects the Car name, in next activity the user can see the Car details with images.
Here I display Details, But I don't know How to display Car Images From Server
Thanks
Here is my Code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_activity);
detailtext= (TextView) findViewById(R.id.detail);
imageView= (ImageView) findViewById(R.id.images);
Intent intent= getIntent();
final String selectedData = intent.getStringExtra("selectedItem");
actionBar.setTitle(selectedData);
dbHelper = new SqlLiteDbHelper(this);
try {
dbHelper.openDataBase();
} catch (SQLException e) {
e.printStackTrace();
}
sqLiteDatabase = dbHelper.getReadableDatabase();
cursor=dbHelper.getdetails(sqLiteDatabase, selectedData);
if (cursor.moveToFirst()) {
detailtext.setText(cursor.getString(0));
String imagename = cursor.getString(1);
String imageUrl = "http://your_server/car/" + imagename ;
Picasso.with(this).load(imageUrl).into(imageView );
}
Note:Image Field is the 4th Column http://i.stack.imgur.com/lqvOQ.png
and in server i put image in www.server.com/cars/carnames.jpg
in sqlite i just paste the image name with .jpg ex:carnames.jpg
SqliteDbHelper
public Cursor getdetails(SQLiteDatabase db,String img)
{
db=this.getReadableDatabase();
Cursor cursor;
cursor=db.query("record",new String[]{DETAIL,IMAGES,ITEMNO + " as _id"},SUBCATEGORY + "='" +img+"'",null,null,null,null);
return cursor;
}
If you want to load images from SQlite then I suggest you save the file/file location if the data is stored locally, for the showing of a single image on all image view it is because you are only loading a single image, you might want to put all your ids in an array and passing it to the db, the db query should also return an array/arraylist of image locations which you should load into your image views using a for loop e.g I have a query that loads a bunch of images from my SQLite database, this displays sub-category images of a certain category named shoes so we have images of smart shoes, Casual shoes and more I pass an an Id as parameter
public ArrayList<CategoryItem> getAllSubCategories(int mtargetID) throws SQLException{
ArrayList<CategoryItem> myshoes = new ArrayList<>();
// Select All Query
String sQuery = " SELECT "+Constant.CATEGORY_TB_ID+", "+Constant.SUB_DESCRIPTION+
", "+Constant.SUB_IMAGEPATH+" FROM "+Constant.CATEGORY_TABLE+
" INNER JOIN "+Constant.SUB_CATEGORY_TABLE+" ON "+Constant.CATEGORY_TB_ID +" = " +Constant.SUB_CATEGORY_FK
+ " WHERE "+Constant.CATEGORY_TB_ID +" = ?";
String[] args = new String[1];
args[0] = String.valueOf(mtargetID);
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(sQuery, args);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
CategoryItem myShoesItem = new CategoryItem();
//my shoe image path on external storage
myShoeItem.setmCategoryImgPath(cursor.getString(2));
//i add my image paths to my array list
myshoes.add(myShoeItem);
} while (cursor.moveToNext());
}
// return my arraylist for display into my imageview
return mshoes;
}
on the receiving side I then transverse through my araylist
for(int i = 0; i <getAllSubCategories.size(); i++ )
{
imageView.setImageUri(getAllSubCategories.get(i).getmCategoryImgPath())
}
with this method you will set images to all your imageviews.
You have the path "url" request to the server? like this:
http://server_ip/api/images?imageName="The name you image here"
Then do you need use some lib to load image from server, see this:
Android Picasso
So, something like this:
Picasso.with(context).load("http://server_ip/api/images?imageName="The name you image here.png/jpeg").into(imageView);
You're saying that in your server, you've created a directory called cars/ and all images are in jpeg format and also with same file name as their real names. If I'm correct, so your can use codes below.
Intent intent= getIntent();
final String selectedData = intent.getStringExtra("selectedItem");
actionBar.setTitle(selectedData);
// This a image declared in XML for displaying car image
ImageView carImageView = (ImageView) findViewById(R.id.carImage);
// URL of this car's image
String imageUrl = "http://your_server_address/cars/" + carName + ".jpeg";
// Use Picasso library to load that image
Picasso.with(this).load(imageUrl).into(carImageView);
Note: Picasso is a fearure rich library for fetching images from network in Android.
I want to save and retrieve the image from local database. I insert image as blob in db but I am usable to retrieve image.
Please help me.
Thanks
Monali
What error are you getting? Using LINQ to SQL, the following code creates an HttpHandler and grabs a BLOB from a database...
public class GetFile : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
Document document = new GigzDataContext().Documents.SingleOrDefault(p => p.Id == new Guid(context.Request.QueryString["Id"].ToString()));
context.Response.ContentType = document.ContentType;
context.Response.BinaryWrite(document.Blob.ToArray());
}
public bool IsReusable
{
get
{
return false;
}
}
}
See this link to have a concept on how to retrieve blob data from a database table as bytes, and after you have them in bytes, you should be able to save them into proper format to form your final image.
I have a query in my android app that pulls all image paths from a custom table and displays them to a gallery. The problem is with my database I cant seem to get a row of the database to a String[]. I can easily get the results to a listArray but I need the image path in a string or string array. I want to be able to click on an image in the gallery and have it pull up full screen to be able to zoom in on it or delete it etc. This is the basic query i use
public void listimages() {
SimpleCursorAdapter adapter;
String[] columns = {"Image", "ImageDate", "_id"};
query = new TableImages(this);
queryString = query.getData("images", columns, null, null, null, null, "ImageDate", "DESC");
int to[] = {R.id._id1, R.id._id2};
adapter = new SimpleCursorAdapter(this, R.layout.imagelist, queryString, columns, to);
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(adapter);
g.setOnItemClickListener(this);
try {
query.destroy();
} catch (Throwable e) {
e.printStackTrace();
}
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(ViewAllImages.this, ImageViewer.class);
Bundle b = new Bundle();
//I want to be able to use this -> b.putString("image_path", Image);
b.putlong("id", id);
i.putExtras(b);
startActivity(i);
}
This passes the ID to my next activity and the next activity queries the DB pulling that one image path. I still have to use a listview to display the image which makes the app crash on the phone due to memory usage (image is too large).
I can compress the image but I need the path as a string and I cant figure out how to do that without creating a custom content provider or adding a textview and using gettext.toString and thats just getto. My head is killing me as it is with all the reading and coding I have done lol. I have searched all over Google and different forums but I am having problems finding an answer.
Is there a way to use the existing query and get a string or a string array as the result?
Thanks.
I just ended up building a custom content provider. Now I have alot more flexability in my queries.