طريقة إضافة واسترجاع صورة من قاعدة بيانات SQLite

Insert, Read, Delete & Update  في SQLite

يوفر Android طرقًا مختلفة لتخزين البيانات محليًا ، لذا فإن استخدام SQLite هو أحد طرق تخزين البيانات. SQLite هي قاعدة بيانات قاعدة استعلام بنية ، ومن ثم يمكننا القول إنها قاعدة بيانات علاقات. يحتوي نظام التشغيل Android على تطبيقه الخاص لإجراء عمليات CRUD (إنشاء وقراءة وتحديث وحذف) ، لذلك يوفر Android مجموعة من الفئات المتاحة في حزم android.database و android.database.sqlite.

أثناء استخدام SQLite ، يمكن أن تكون هناك طريقتان مختلفتان لإجراء عمليات مختلفة مثل الإنشاء والقراءة والتحديث والحذف. أحدهما يكتب استعلامات خام والآخر يستخدم وظائف ذات معلمات أو يمكننا أن نقول استعلامات ذات معلمات.
عمليات قاعدة بيانات سكليتي
Create : يعد إنشاء قاعدة بيانات أمرًا بسيطًا جدًا في نظام Android باستخدام فئة SQLiteOpenHelper. SQLiteOpenHelper هي فئة مجردة مع طريقتين مجردتين onCreate (SQLiteDatabase db) و onUpgrade (SQLiteDatabase db و int oldVersion و int newVersion) والعديد من الوظائف المفيدة لقاعدة البيانات. كلما احتجنا إلى إنشاء قاعدة بيانات ، يتعين علينا توسيع فئة SQLiteOpenHelper على النحو التالي:

/**A helper class to perform database related queries*/

	public class SqliteManager extends SQLiteOpenHelper {
	public static final String DATABASE_NAME = "abhiandroid.db";
	public static final int version = 1;

	public SqliteManager(Context context) {
	super(context, DATABASE_NAME, null, version);
	}

	@Override
	public void onCreate(SQLiteDatabase sqLiteDatabase) {
	String dbQuery = "CREATE TABLE Items (id INTEGER PRIMARY KEY                          
	AUTOINCREMENT,name TEXT, description TEXT)";
	sqLiteDatabase.execSQL(dbQuery);
	}

	@Override
	public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
	}
	}

يتم استدعاء طريقة

onCreate (SQLiteDatabase sqLiteDatabase) 

لمرة واحدة فقط طوال دورة حياة التطبيق ، وسوف يتم استدعاؤها كلما كان هناك أول استدعاء لوظيفة getReadableDatabase () أو getWritableDatabase () المتوفرة في فئة super SQLiteOpenHelper ، لذلك تقوم فئة SQLiteOpenHelper باستدعاء طريقة onCreate () بعد الإنشاء قاعدة بيانات وإنشاء كائن SQLiteDatabase. تم تمرير اسم قاعدة البيانات في استدعاء المُنشئ.

لا يتم استدعاء 

onUpgrade (SQLiteDatabase db ، int oldVersion ، int newVersion)

إلا عندما يكون هناك تحديث في الإصدار الحالي ، لذلك لتحديث إصدار ، يتعين علينا زيادة قيمة متغير الإصدار الذي تم تمريره في مُنشئ الفئة الفائقة. في طريقة onUpgrade يمكننا كتابة استعلامات لأداء أي إجراء مطلوب. في معظم الأمثلة ، سترى أنه يتم إسقاط الجدول (الجداول) الموجودة ومرة ​​أخرى يتم استدعاء طريقة onCreate () لإنشاء الجداول مرة أخرى. لكن ليس من الضروري القيام بذلك ، فكل هذا يتوقف على متطلباتك. يتعين علينا تغيير إصدار قاعدة البيانات إذا أضفنا صفًا جديدًا في جدول قاعدة البيانات في هذه الحالة إذا كان لدينا متطلبات لا نريد فقدان البيانات الموجودة في الجدول ، فيمكننا كتابة استعلام جدول بديل في onUpgrade (SQLiteDatabase db ، int oldVersion ، int newVersion) الطريقة.

وبالمثل ، إذا لم تكن هناك متطلبات للبيانات الموجودة كلما قمنا بترقية إصدار قاعدة البيانات ، فيمكننا كتابة استعلام جدول الإسقاط في أسلوب onUpgrade (SQLiteDatabase db ، int oldVersion ، int newVersion) واستدعاء طريقة onCreate (SQLiteDatabase sqLiteDatabase) مرة أخرى لإنشاء الجدول مرة أخرى. تذكر عدم استدعاء أسلوب onCreate (SQLiteDatabase sqLiteDatabase) إذا كنت قد كتبت استعلام جدول بديل في أسلوب onUpgrade (SQLiteDatabase db ، int oldVersion ، int newVersion).


عملية Insert, Read, Delete & Update في Sqlite

لإجراء عملية الإدراج والقراءة والحذف والتحديث ، هناك طريقتان مختلفتان:

  • كتابة استعلامات ذات معلمات (مستحسن)
  • اكتب استفسارات أولية

استعلامات ذات معلمات: هذه هي تلك الاستعلامات التي يتم إجراؤها باستخدام وظائف داخلية لإدراج البيانات أو قراءتها أو حذفها أو تحديثها. يتم توفير هذه الوظائف المتعلقة بالعملية في فئة SQLiteDatabase.

الاستعلامات الأولية: هذه استعلامات sql بسيطة مشابهة لقواعد البيانات الأخرى مثل MySql و Sql Server وما إلى ذلك ، في هذه الحالة سيتعين على المستخدم كتابة استعلام كنص وتمرير سلسلة الاستعلام في rawQuery (String sql أو String [] selectArgs) أو execSQL (سلسلة) sql ، كائن [] bindArgs) لإجراء العمليات.

ملاحظة مهمة: لا توصي وثائق Android باستخدام الاستعلامات الأولية لإجراء عمليات الإدراج ، والقراءة ، والتحديث ، والحذف ، واستخدام وظائف إدراج فئة SQLiteDatabase واستعلامها وتحديثها وحذفها دائمًا.

فيما يلي مثال على الاستعلام الأولي لإدخال البيانات:

public void insertItem(Item item) {
  String query = "INSERT INTO " + ItemTable.NAME + " VALUES (0,?,?)";
  SQLiteDatabase db = getWritableDatabase();
  db.execSQL(query, new String[]{item.name, item.description});
  db.close();
}

أثناء استخدام الاستعلامات الأولية ، لم نتوصل أبدًا إلى معرفة نتيجة العملية ، ولكن مع وظيفة الاستعلامات ذات المعلمات ، يتم إرجاع قيمة لنجاح العملية أو فشلها.

Insert  لإجراء عملية الاضافه  باستخدام استعلام ذي معلمات ، يتعين علينا استدعاء وظيفة الإدراج المتوفرة في فئة SQLiteDatabase. تحتوي وظيفة insert () على ثلاث معلمات مثل الإدراج العام الطويل (String tableName ، String nullColumnHack ، قيم ContentValues) حيث يكون اسم الجدول هو اسم الجدول الذي سيتم إدراج البيانات فيه.

public long insert(String tableName,String nullColumnHack,ContentValues values)

قد يتم تمرير NullColumnHack فارغًا ، فهو يتطلب قيمة عمود الجدول في حالة عدم وضع اسم العمود في كائن ContentValues ​​لذلك يجب إدراج قيمة فارغة لهذا العمود المحدد ، والقيم هي تلك القيم التي يجب إدراجها- ContentValues ​​هي مفتاح- كائن قائم على الزوج يقبل جميع قيم النوع البدائي ، لذلك عندما يتم وضع البيانات في كائن ContentValues ​​، يجب وضعها مرة أخرى اسم عمود الجدول كمفتاح والبيانات كقيمة. تُرجع الدالة insert قيمة طويلة ، أي رقم الصف المُدرج إذا تم إدراجه بنجاح ، - 1 بخلاف ذلك.

هنا مثال بسيط:

//Item is a class representing any item with id, name and description.
public void addItem(Item item) {
SQLiteDatabase db = getWritableDatabase();
	ContentValues contentValues = new ContentValues();
	contentValues.put("name",item.name);
	// name - column
	contentValues.put("description",item.description);
	// description is column in items table, item.description has value for description
	db.insert("Items", null, contentValues);//Items is table name
	db.close();
	}

Update :  وظيفة التحديث مشابهة تمامًا للإدراج ولكنها تتطلب معلمتين إضافيتين ، فهي لا تتطلب nullColumnHack. يحتوي على أربع معلمات إجمالاً ، وهما متشابهة لإدراج وظيفة هي اسم الجدول وقيم المحتوى. اثنان آخران هما whereClause (String) و whereArgs (String []).

تتوفر وظيفة التحديث في فئة SQLiteDatabase وهي تبدو كما يلي:

public int update(String tableName,ContentValues contentValues,String whereClause,String[] whereArgs)
	

هنا حيث حيث يتم إخبار قاعدة البيانات بمكان تحديث البيانات في الجدول ، يوصى بتمرير (الأسئلة) مع اسم العمود في whereClause String. وبالمثل ، حيث ستحتوي مصفوفة Args على قيم لتلك الأعمدة التي تم وضع "ق" مقابلها في whereClause. ستعيد وظيفة التحديث عدد الصفوف المتأثرة إذا نجحت ، 0 وإلا.

هنا استخدام بسيط للتحديث:

//Item is a class representing any item with id, name and description
	public void updateItem(Item item) {
	SQLiteDatabase db = getWritableDatabase();
	ContentValues contentValues = new ContentValues();
	contentValues.put("id", item.id);
	contentValues.put("name", item.name);
	contentValues.put("description", item.description);
	String whereClause = "id=?";
	String whereArgs[] = {item.id.toString()};
	db.update("Items", contentValues, whereClause, whereArgs);
	}

Delete : على غرار الإدراج والتحديث ، تتوفر وظيفة الحذف في فئة SQLiteDatabase ، لذا فإن الحذف يشبه إلى حد كبير تحديث الوظيفة بصرف النظر عن كائن ContentValues ​​لأنه غير مطلوب في الحذف. public int delete (String tableName، String whereClause، String [] whereArgs) تحتوي على ثلاث معلمات تشبه تمامًا معلمات وظيفة التحديث وتستخدم بنفس الطريقة كما في وظيفة التحديث.

هنا استخدام بسيط للحذف:

public void deleteItem(Item item) {
	SQLiteDatabase db = getWritableDatabase();
String whereClause = "id=?";
String whereArgs[] = {item.id.toString()};
db.delete("Items", whereClause, whereArgs);
}

هنا حيث يكون السبب اختياريًا ، سيؤدي تمرير القيمة الفارغة إلى حذف جميع الصفوف في الجدول. ستعيد وظيفة الحذف رقم الصف المتأثر إذا تم تمرير الشرط الذي تم تمريره بخلاف ذلك سيعود 0.

ملاحظة مهمة: إذا كنت تريد إزالة جميع الصفوف وتطلب عدد الصفوف المحذوفة ، فقم بتمرير 1 كـ whereClause .

قراءة (select): تختلف القراءة من جدول قاعدة البيانات قليلاً عن الوظائف الأخرى مثل الإدراج والتحديث والحذف. توفر فئة SQLiteDatabaseطريقة استعلام () لقراءة البيانات من الجدول. طريقة الاستعلام () محملة بشكل زائد بمجموعة مختلفة من المعلمات. تقوم بإرجاعكائن المؤشر ، لذا فإن المؤشر عبارة عن مجموعة نتائج تحتوي على بيانات تم الاستعلام عنها ، ويوفر وظائف مختلفة مفيدة حقًا أثناء قراءة البيانات.

فيما يلي بعض وظائف الاستعلام المحملة بشكل زائد:

  •  
  • public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
  • public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
  • public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)

معظم المعلمات في وظائف الاستعلام المحملة بشكل زائد اختيارية باستثناء من الجدول ويمكن تمرير أي من المعلمات الأخرى على أنها خالية. إذا تم تمرير علامة مميزة على أنها مجموعة بيانات المؤشر الحقيقية فلن تحتوي على أي صف مكرر.

public ArrayList<Item> readAllItems() {
ArrayList<Item> items = new ArrayList<>();
SQLiteDatabase db = getReadableDatabase();
//see above point 2 function
Cursor cursor = db.query("Items"
, null// columns - null will give all
, null// selection 
, null// selection arguments
, null// groupBy
, null// having 
	, null// no need or order by for now;
		if (cursor != null) {
	  while (cursor.moveToNext()) {
	// move the cursor to next row if there is any to read it's data
	          Item item = readItem(cursor);
  items.add(item);
  }
	}
		return items;
		  }

			private Item readItem(Cursor cursor) {
			Item item = new Item();
			  item.id = cursor.getInt(cursor.getColumnIndex(ItemTable.COL_ID));
				item.name = cursor.getString(cursor.getColumnIndex(ItemTable.COL_NAME));
				  item.description = cursor.getString(cursor.getColumnIndex(ItemTable.COL_DESCRIPTION));
				return item;
				}

طريقة إضافة واسترجاع صورة من قاعدة بيانات SQLite

سنناقش الآن   كيفية إضافة أو استرداد الصورة من وحدة التخزين الخارجية للهاتف إلى التطبيق باستخدام قاعدة بيانات SQLite. نقوم في الأساس بإنشاء قاعدة بيانات وجدول في التطبيق باستخدام SQLite. سيحتوي الجدول على الصورة التي تم جلبها من وحدة التخزين الخارجية.

يوجد اختلاف أثناء الاسترداد بمستوى API مختلف. تم تغيير مفهوم الإذن منذ API 23. قبل مستوى API 23 ، سُئل المستخدم أثناء التثبيت وبعد مستوى API 23 يُطلب من المستخدم أثناء وقت التشغيل. لذلك ، تمت إضافة إذن وقت تشغيل إضافي في التطبيق الذي يعمل على مستوى API أعلى من 23.

فيما يلي شرح للطريقتين خطوة بخطوة لإضافة أو استرداد صورة من قاعدة بيانات SQLite.




مثال 1:  إضافة واسترجاع الصورة من قاعدة بيانات SQLite (أقل من مستوى API 23)

في هذا المثال ، استخدمنا الأزرار و imageview لإنشاء واجهة المستخدم ، تتم إضافة الزر عند النقر ويتم تحديد الطرق في فئة جافا المقابلة.

كود التحميل

إضافة أو استرجاع الصورة باستخدام SQLite

الخطوة 1: قم بإنشاء مشروع جديد وقم بتسميته SqliteImageDemo .

الخطوة 2: افتح ملف AndroidManifest.xml وأضف إذنًا للوصول إلى وحدة التخزين الخارجية.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

الخطوة 3: افتح res -> layout -> activity_main.xml (أو) main.xml وأضف الكود التالي:

في هذا الكود ، قم ببساطة بإضافة imageeview وزر مع وظيفة onclick.

<?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/activity_main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.example.sqliteimagedemo.MainActivity">

  <Button
  android:text="@string/get_image"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="19dp"
  android:id="@+id/button"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:onClick="save"/>

  <Button
  android:text="@string/view_image"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="29dp"
  android:id="@+id/button2"
  android:layout_below="@+id/button"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:onClick="get"/>

  <ImageView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:srcCompat="@mipmap/ic_launcher"
  android:id="@+id/imageView"
  android:layout_below="@+id/button2"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginTop="43dp"
  tools:ignore="ContentDescription" />
  </RelativeLayout>

الخطوة 4: افتح src -> package -> MainActivity.java

في هذه الخطوة ، نفتح MainActivity ونضيف الوظائف المحددة عبر الزر عند النقر على أي حفظ أو الحصول. تحتوي طريقة الحفظ على FileInputStream للحصول على ملف من المسار المحدد وحفظه في قاعدة البيانات. علاوة على ذلك ، يتم إدراج الصورة في الجدول باستخدام SQLiteDatabase ، ويتم استخدام Toast للإشارة إلى اكتمال العملية. تستخدم طريقة get عبارة تحديد SQLite لاسترداد الصورة المحفوظة وعرضها في imageeview.

package com.example.sqliteimagedemo;

  import android.content.ContentValues;
  import android.content.Context;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.ImageView;
  import android.widget.Toast;
  import java.io.FileInputStream;
  import java.io.IOException;

  public class MainActivity extends AppCompatActivity {
  ImageView imageView;
  SQLiteDatabase db;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  imageView = (ImageView) findViewById(R.id.imageView);
  //database created
  db = this.openOrCreateDatabase("test.db", Context.MODE_PRIVATE,null);
  //table created
  db.execSQL("create table if not exists imageTb ( a blob )");
  }

  public  void save(View view) throws IOException {
  FileInputStream fis = new FileInputStream("/storage/sdcard/demoImage.jpg");
  byte[] image= new byte[fis.available()];
  fis.read(image);
  ContentValues values = new ContentValues();
  values.put("a",image);
  db.insert("imageTb", null,values);
  fis.close();
  Toast.makeText(this,"Done", Toast.LENGTH_SHORT).show();
  }
  public void get(View view) {
  Cursor c = db.rawQuery("select * from imageTb", null);
  if(c.moveToNext())
  {
  byte[] image = c.getBlob(0);
  Bitmap bmp= BitmapFactory.decodeByteArray(image, 0 , image.length);
  imageView.setImageBitmap(bmp);
  Toast.makeText(this,"Done", Toast.LENGTH_SHORT).show();
  }
  }
  }

المخرجات :

الآن قم بتشغيل التطبيق وانقر فوق الزر لإضافة واسترداد الصورة في التطبيق.


مثال 2: إضافة واسترجاع صورة من قاعدة بيانات SQLite (أعلى مستوى API 23)

في هذا المثال ، استخدمنا الأزرار و imageview لإنشاء واجهة المستخدم ، تتم إضافة الزر عند النقر ويتم تحديد الطرق في فئة جافا المقابلة. الاختلاف الأساسي هو أننا نحتاج إلى تحديد الأذونات في وقت التشغيل.

كود التحميل

إضافة أو استرداد مثال الصورة باستخدام SQLite
الخطوة 1: قم بإنشاء مشروع جديد وقم بتسميته SqliteImageDemo .
الخطوة 2: افتح ملف AndroidManifest.xml وأضف إذنًا للوصول إلى وحدة التخزين الخارجية.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

الخطوة 3: افتح res -> layout -> activity_main.xml (أو) main.xml وأضف الكود التالي:
في هذا الكود ، أضف ببساطة imageview وزرًا بوظيفة onclick.

<?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/activity_main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.example.sqliteimagedemo.MainActivity">

  <ImageView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:srcCompat="@mipmap/ic_launcher"
  android:layout_marginTop="61dp"
  android:id="@+id/imageView"
  android:layout_below="@+id/button1"
  android:layout_alignLeft="@+id/button1"
  android:layout_alignStart="@+id/button1" />

  <Button
  android:text="VIEW  FETCHED IMAGE"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:id="@+id/button2"
  android:onClick="viewImage"
  android:layout_below="@+id/button1"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true" />

  <Button
  android:text="FETCH IMAGE FROM EXTERNAL STORAGE"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:id="@+id/button1"
  android:onClick="fetchImage"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true" />

  </RelativeLayout>

الخطوة 4: افتح src -> package -> MainActivity.java

في هذه الخطوة ، نفتح MainActivity ونضيف الوظائف المحددة عبر الزر عند النقر على أي حفظ أو الحصول. تحتوي طريقة الحفظ على FileInputStream للحصول على ملف من المسار المحدد وحفظه في قاعدة البيانات. علاوة على ذلك ، يتم إدراج الصورة في الجدول باستخدام SQLiteDatabase ، ويتم استخدام Toast للإشارة إلى اكتمال العملية. تستخدم طريقة get عبارة تحديد SQLite لاسترداد الصورة المحفوظة وعرضها في imageeview.

بالإضافة إلى واجهة برمجة التطبيقات السابقة ، تتم إضافة بيان يمثل في الأساس إذنًا لقراءة / كتابة وحدة التخزين الخارجية.

package com.example.sqliteimagedemo;

  import android.Manifest;
  import android.content.ContentValues;
  import android.content.Context;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.os.Environment;
  import android.support.v4.app.ActivityCompat;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.ImageView;
  import android.widget.Toast;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;


  public class MainActivity extends AppCompatActivity {

  private int STORAGE_PERMISSION_CODE = 23;
  ImageView imageView;
  SQLiteDatabase db;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  //Permission to access external storage
  ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},STORAGE_PERMISSION_CODE);
  imageView = (ImageView) findViewById(R.id.imageView);
  //creating database
  db = this.openOrCreateDatabase("test.db", Context.MODE_PRIVATE,null);
  //creating table for storing image
  db.execSQL("create table if not exists imageTb ( image blob )");
  }

  public void viewImage(View view)
  {
  Cursor c = db.rawQuery("select * from imageTb", null);
  if(c.moveToNext())
  {
  byte[] image = c.getBlob(0);
  Bitmap bmp= BitmapFactory.decodeByteArray(image, 0 , image.length);
  imageView.setImageBitmap(bmp);
  Toast.makeText(this,"Done", Toast.LENGTH_SHORT).show();
  }
  }

  public  void fetchImage(View view) throws IOException {

  File folder= new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/demoImage.jpg/");
  FileInputStream fis = new FileInputStream(folder);
  byte[] image= new byte[fis.available()];
  fis.read(image);
  ContentValues values = new ContentValues();
  values.put("image",image);
  db.insert("imageTb", null,values);
  fis.close();
  Toast.makeText(this,"Image Fetched", Toast.LENGTH_SHORT).show();
  }
  }

المخرج :

الآن قم بتشغيل التطبيق وانقر فوق الزر لإضافة واسترداد الصورة في التطبيق.