شرح الكاميرا Camera في الاندرويد

برنامج تعليمي للكاميرا مع مثال في Android Studio خطوة بخطوة

في Android ، تعد الكاميرا جهازًا يسمح بالتقاط الصور ومقاطع الفيديو في تطبيقاتك. اتبع هذا البرنامج التعليمي لتفهم بسهولة كيفية استخدام الكاميرا في تطبيق Android الخاص بك.

Camera Tutorial Example In Android Studio

يوفر إطار عمل Android سهولة العمل مع الكاميرا بطريقتين:

1. عن طريق استخدام تطبيق الكاميرا الموجود
2. باستخدام Camera Api

# 1 استخدام الكاميرا باستخدام تطبيق الكاميرا

يمكننا التقاط الصور دون استخدام مثيل فئة الكاميرا. هنا سوف تستخدم نوع إجراء مقصود من MediaStore.ACTION_IMAGE_CAPTURE لبدء تشغيل تطبيق كاميرا موجود على هاتفك. في Android ، يعد MediaStore نوعًا من DataBase الذي يخزن الصور ومقاطع الفيديو في android.

Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

# 2 استخدام الكاميرا باستخدام Camera Api

تستخدم هذه الفئة للتحكم في كاميرات الجهاز. يمكن استخدامه لالتقاط الصور عند إنشاء تطبيق الكاميرا.
تعمل Camera API بالطرق التالية:

1. مدير الكاميرا : يستخدم هذا للحصول على جميع الكاميرات المتوفرة في الجهاز مثل الكاميرا الأمامية والكاميرا الخلفية لكل منها معرف الكاميرا.

2. جهاز الكاميرا : يمكنك الحصول عليها من فئة مدير الكاميرا من خلال معرفها.

3. CaptureRequest : يمكنك إنشاء طلب التقاط من جهاز الكاميرا لالتقاط الصور.

4. CameraCaptureSession : للحصول على طلبات الالتقاط من جهاز الكاميرا ، قم بإنشاء جلسة CameraCaptureSession.

5. CameraCaptureSession.CaptureCallback : سيوفر هذا نتائج جلسة الالتقاط.

تصريحات إذن الكاميرا في البيان

أولاً ، يجب أن تعلن عن متطلبات الكاميرا في ملف Manifest الخاص بك إذا كانت الكاميرا إلزامية لتطبيقك ولا تريد تثبيت التطبيق الخاص بك على جهاز لا يدعم الكاميرا.

قبل أن تبدأ في تطوير تطبيقك ، عليك التأكد من أن البيان الخاص بك يحتوي على تصريحات مناسبة تسمح لك باستخدام ميزة الكاميرا في تطبيقك.

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

مثال على الكاميرا في Android Studio باستخدام هدف الكاميرا وتخزين صورة الكاميرا في قاعدة البيانات المحلية

في مثال الكاميرا في Android ، سأوضح لك كيفية التقاط الصورة من كاميرا الجهاز باستخدام Intent وتخزين صورة الكاميرا هذه في قاعدة البيانات المحلية وعرض نخب عند تخزين الصورة بنجاح أو عند حدوث خطأ ما أثناء تخزين الصورة.

Camera Tutorial Example In Android Studio

يمكنك أدناه تنزيل الكود ، والاطلاع على الإخراج النهائي والشرح خطوة بخطوة للمثال:

قم بتنزيل مثال الكاميرا في Android Code من Github

الخطوة 1 : أنشئ مشروعًا جديدًا في Android Studio وقم بتسميته CameraCodeExample

الخطوة 2 : افتح res -> layout -> xml أو (activity_main. xml ) وأضف الكود التالي
هنا لقد استخدمت تخطيط الإطار لتحميل الأجزاء.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <FrameLayout
  android:id="@+id/frameLayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"/>
  </RelativeLayout>

الخطوة 3 : افتح src -> package -> MainActivity. java
هنا أقوم بتحميل الجزء الافتراضي الخاص بي في تخطيط الإطار في MainActivity:

import android.Manifest;
  import android.app.Activity;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.graphics.Bitmap;
  import android.os.Build;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.support.annotation.RequiresApi;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentTransaction;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.FrameLayout;
  import android.widget.ImageView;
  import android.widget.TextView;
  import android.widget.Toast;

  import com.example.cameracodeexample.Fragments.CameraFragment;

  public class MainActivity extends AppCompatActivity {

  FrameLayout frameLayout;

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

  loadFragment(new CameraFragment(), false);

  }

  public void loadFragment(Fragment fragment, Boolean bool) {
  FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
  transaction.replace(R.id.frameLayout, fragment);
  if (bool)
  transaction.addToBackStack(null);
  transaction.commit();
  }

  }

الخطوة 4 : افتح الدقة -> التخطيط -> xml أو (camera_fragment.xml)
هنا لقد استخدمت عرضين نصيين ، يمكنك النقر فوق صورة وحفظها في DataBase والآخر لعرض تلك الصورة المخزنة.

<TextView
  android:id="@+id/text"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="Save Image"
  android:layout_gravity="center"
  android:layout_margin="@dimen/_12sdp"
  android:textSize="@dimen/_18sdp"
  android:textAlignment="center"
  android:background="#EBEBEB"/>
  TextView
  <android:id="@+id/text1"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="View Image"
  android:layout_gravity="center"
  android:layout_margin="@dimen/_12sdp"
  android:textSize="@dimen/_18sdp"
  android:textAlignment="center"
  android:background="#EBEBEB"
  android:layout_below="@id/text"/>

الخطوة الخامسة: الآن سأشرح الطرق المستخدمة في CameraFragment:

التحقق من أذونات الكاميرا:

لأول مرة استخدمنا وظيفة requestPermissions (سلسلة جديدة [] {Manifest.permission.CAMERA} ، MY_CAMERA_PERMISSION_CODE) ؛
سوف نتحقق مما إذا كان المستخدم قد منح أذونات أم لا ، إذا لم يكن الأمر كذلك ، فسنطلب أولاً من المستخدم أذونات إذا كان المستخدم يستخدم إصدار Android أعلى من Android Marshmallow (API 23) لأنه من Android Marshmallow (API 23) وما فوق بشكل افتراضي ، كل شيء خطير إذن تعطيل. عند فتح التطبيق لأول مرة بعد التثبيت ، يجب عليك منح الأذونات. ولكن إذا كان إصدار android أقل من Marshmallow ، فلن يتم استدعاء هذه الوظيفة.

requestPermissions(newString[]{Manifest.permission.CAMERA},MY_CAMERA_PERMISSION_CODE)

startActivityForResult (cameraIntent ، CAMERA_REQUEST) الطريقة:

الآن سوف نسمي Function startActivityForResult (cameraIntent، CAMERA_REQUEST) ؛
عندما تبدأ نشاطًا للنتيجة ، فإنها تطلب من الكاميرا التقاط صورة ثم إعادتها إلى نشاط الاتصال الخاص بك ، أو تقوم بتمريرها بقيمة عدد صحيح فريد أو أي شيء لم تستخدمه بالفعل في تلك الفئة. يساعدك requestCode في تحديد النية التي رجعت منها.
لذلك ، يمكن أن تكون CAMERA_REQUEST أي قيمة تحددها في فصلك مثل هذا:

private static final int CAMERA_REQUEST = 1888
 
  @Override
  public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
  {
  theImage = (Bitmap) data.getExtras().get("data");
  photo=getEncodedString(theImage);
  setDataToDataBase();
  }
  }

طريقة getEncodedString (صورة نقطية نقطية):

منذ الآن يمكنني النقر فوق صورة من الكاميرا ولكن هذه الصورة في شكل صورة نقطية ولكني أريد تخزينها كسلسلة في قاعدة البيانات ، لذلك سأقوم بتشفيرها باستخدام ByteArrayOutputStream Class. يحتفظ هذا الفصل بنسخة من البيانات ويعيد توجيهها إلى تدفقات متعددة.

private String getEncodedString(Bitmap bitmap){

  ByteArrayOutputStream os = new ByteArrayOutputStream();

  bitmap.compress(Bitmap.CompressFormat.JPEG,100, os);

  /* or use below if you want 32 bit images

  bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);*/

  byte[] imageArr = os.toByteArray();

  return Base64.encodeToString(imageArr, Base64.URL_SAFE);

  }

طريقة setDataToDataBase ():

الآن أقوم بتخزين البيانات (صورة) في قاعدة بيانات (هنا استخدمت SQLite). هنا تساعد فئة ContentValue على وضع المعلومات داخل كائن في شكل أزواج Key-Value للأعمدة. لإدراج أو تحديث WritableDatabase الخاص بك يمكن بعد ذلك تمرير الكائن إلى مثيل من فئة SQLiteDatabase.

private void setDataToDataBase() {
  db = databaseHandler.getWritableDatabase();
  ContentValues cv = new ContentValues();
  cv.put(databaseHandler.KEY_IMG_URL,photo);

  long id = db.insert(databaseHandler.TABLE_NAME, null, cv);
  if (id < 0) {
  Toast.makeText(getContext(), "Something went wrong. Please try again later...", Toast.LENGTH_LONG).show();
  } else {
  Toast.makeText(getContext(), "Add successful", Toast.LENGTH_LONG).show();
  }
  }

الخطوة 6 : افتح src -> package -> CameraFragment.جافا

في هذه الخطوة نفتح CameraFragment ونضيف الكود لبدء الكاميرا هنا نقوم بمجموعة من العمليات للنقر فوق صورة من الكاميرا وتخزينها في قاعدة البيانات

import android.Manifest;
  import android.app.Activity;
  import android.content.ContentValues;
  import android.content.Context;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.database.sqlite.SQLiteDatabase;
  import android.graphics.Bitmap;
  import android.os.Build;
  import android.os.Bundle;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.support.annotation.RequiresApi;
  import android.support.v4.app.Fragment;
  import android.util.Base64;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.TextView;
  import android.widget.Toast;
  import com.example.cameracodeexample.MainActivity;
  import com.example.cameracodeexample.R;
  import com.example.cameracodeexample.utils.DataBaseHandler;
  import java.io.ByteArrayOutputStream;

  public class CameraFragment extends Fragment {
  private static final int CAMERA_REQUEST = 1888;
  TextView text,text1;
  private static final int MY_CAMERA_PERMISSION_CODE = 100;
  //Bitmap photo;
  String photo;
  DataBaseHandler databaseHandler;
  private SQLiteDatabase db;
  Bitmap theImage;
  @Nullable
  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  View view = inflater.inflate(R.layout.camera_fragment,container,false);


  // imageView =view. findViewById(R.id.imageView1);
  text = view.findViewById(R.id.text);
  text1 = view.findViewById(R.id.text1);
  databaseHandler = new DataBaseHandler(getContext());
  text.setOnClickListener(new View.OnClickListener() {
  @RequiresApi(api = Build.VERSION_CODES.M)
  @Override
  public void onClick(View v) {
  if (getActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
  {
  requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
  }
  else
  {
  Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  startActivityForResult(cameraIntent, CAMERA_REQUEST);
  }
  }
  });

  text1.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  ((MainActivity) getActivity()).loadFragment(new LocalFragment(), true);
  }
  });
  return view;
  }

  private void setDataToDataBase() {
  db = databaseHandler.getWritableDatabase();
  ContentValues cv = new ContentValues();
  cv.put(databaseHandler.KEY_IMG_URL,photo);

  long id = db.insert(databaseHandler.TABLE_NAME, null, cv);
  if (id < 0) {
  Toast.makeText(getContext(), "Something went wrong. Please try again later...", Toast.LENGTH_LONG).show();
  } else {
  Toast.makeText(getContext(), "Add successful", Toast.LENGTH_LONG).show();
  }
  }

  /**
  * Reuqesting for premissons
  * @param requestCode
  * @param permissions
  * @param grantResults
  */

  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  if (requestCode == MY_CAMERA_PERMISSION_CODE)
  {
  if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
  {
  Toast.makeText(getActivity(), "camera permission granted", Toast.LENGTH_LONG).show();
  Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  startActivityForResult(cameraIntent, CAMERA_REQUEST);
  }
  else
  {
  Toast.makeText(getActivity(), "camera permission denied", Toast.LENGTH_LONG).show();
  }
  }
  }

  /**
  * Start an activity for result
  * @param requestCode
  * @param resultCode
  * @param data
  */

  @Override
  public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
  {
  theImage = (Bitmap) data.getExtras().get("data");
  photo=getEncodedString(theImage);
  setDataToDataBase();
  }
  }


  private String getEncodedString(Bitmap bitmap){

  ByteArrayOutputStream os = new ByteArrayOutputStream();

  bitmap.compress(Bitmap.CompressFormat.JPEG,100, os);

  /* or use below if you want 32 bit images

  bitmap.compress(Bitmap.CompressFormat.PNG, (0–100 compression), os);*/
  byte[] imageArr = os.toByteArray();
  return Base64.encodeToString(imageArr, Base64.URL_SAFE);

  }
  }

الخطوة 7 : افتح src -> package -> DataBaseHandler Class.جافا

هنا نحدد المخطط ، أي اسم قاعدة البيانات والإصدار وأسماء الجدول وأسماء الأعمدة. نظرًا لأن هذه الفئة تمتد إلى SQLiteOpenHelper ، فإنها تقول لتنفيذ طريقتين
1.onCreate () - يتم استدعاء هذه الطريقة بواسطة إطار العمل ، إذا لم يتم إنشاء قاعدة البيانات بعد ولكن تم الوصول إليها فقط.
2.onUpgrade () - تسمى هذه الطريقة إذا كنت تريد إضافة شيء ما في قاعدة البيانات ، فيجب عليك ترقية إصدار قاعدة البيانات الخاصة بك. تساعد هذه الطريقة في تحديث مخطط قاعدة البيانات الحالي أو إسقاط الجدول أو إعادة إنشائه عبر طريقة الإنشاء.
طريقة public void deleteEntry (صف طويل) - تُستخدم هذه الطريقة لحذف إدخال في قاعدة البيانات استنادًا إلى uid.

import android.content.Context;
  import android.database.sqlite.SQLiteDatabase;
  import android.database.sqlite.SQLiteOpenHelper;


  public class DataBaseHandler extends SQLiteOpenHelper {
  public Context context;
  public static final String DATABASE_NAME = "dataManager";

  public static final int DATABASE_VERSION = 1;
  public static final String TABLE_NAME = "data";
  public static final String KEY_ID = "id";
  public static final String KEY_IMG_URL = "ImgFavourite";

  public DataBaseHandler(Context context) {
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
  this.context = context;
  //Toast.makeText(context, "Constructor called", Toast.LENGTH_LONG).show();
  }

  public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + KEY_ID +
  " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_IMG_URL + " TEXT" + ")";
  public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME + "";

  @Override
  public void onCreate(SQLiteDatabase db) {
  db.execSQL(CREATE_TABLE);
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  db.execSQL(DROP_TABLE);
  onCreate(db);
  }

  public void deleteEntry(long row) {
  SQLiteDatabase sqLiteDatabase = getWritableDatabase();
  sqLiteDatabase.delete(TABLE_NAME, KEY_ID + "=" + row, null);
  }

  }

الخطوة 8 : افتح res -> layout -> xml أو (local_fragment.xml)
في هذا الجزء ، استخدمت عرض Recycler لإظهار البيانات المخزنة في DataBase.

Local_fragment.xml

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:background="@color/color_white"/>
  <android.support.v7.widget.RecyclerView
  android:id="@+id/recyclerview"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="@dimen/_5sdp"
  android:background="@color/color_white"
  android:padding="3dp"
  android:scrollbars="none"/>
  </LinearLayout>

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

هذه هي فئة النموذج التي تملأ البيانات في المحول هنا ، تمثل السلسلة السلسلة المشفرة (الصورة) التي تم حفظها في قاعدة البيانات وتمثل int البيانات المعنية التي سنقوم بتجميعها.

public class LocalResponse {
  String image;
  int uid;

  public int getUid() {
  return uid;
  }

  public void setUid(int uid) {
  this.uid = uid;
  }

  public String getImage() {
  return image;
  }

  public void setImage(String image) {
  this.image = image;
  }

  public LocalResponse(String image, int uid) {
  this.image = image;
  this.uid = uid;
  }
  }

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

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

import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.os.Bundle;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.support.v4.app.Fragment;
  import android.support.v7.widget.LinearLayoutManager;
  import android.support.v7.widget.RecyclerView;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import com.example.cameracodeexample.utils.DataBaseHandler;
  import com.example.cameracodeexample.utils.LocalDataBaseAdapter;
  import com.example.cameracodeexample.utils.LocalResponse;
  import java.util.ArrayList;

  public class LocalFragment extends Fragment {
  RecyclerView recyclerView;
  private DataBaseHandler myDatabase;
  private SQLiteDatabase db;
  private ArrayList singleRowArrayList;
  private LocalResponse singleRow;
  String image;
  int uid;
  Cursor cursor;

  @Nullable
  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  View view = inflater.inflate(R.layout.local_fragment,container,false);
  recyclerView = view.findViewById(R.id.recyclerview);
  myDatabase = new DataBaseHandler(getContext());
  db = myDatabase.getWritableDatabase();
  setData();
  return view;
  }

  private void setData() {
  db = myDatabase.getWritableDatabase();
  RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
  recyclerView.setLayoutManager(layoutManager);
  singleRowArrayList = new ArrayList<>();
  String[] columns = {DataBaseHandler.KEY_ID, DataBaseHandler.KEY_IMG_URL};
  cursor = db.query(DataBaseHandler.TABLE_NAME, columns, null, null, null, null, null);
  while (cursor.moveToNext()) {

  int index1 = cursor.getColumnIndex(DataBaseHandler.KEY_ID);
  int index2 = cursor.getColumnIndex(DataBaseHandler.KEY_IMG_URL);

  uid = cursor.getInt(index1);
  image = cursor.getString(index2);

  singleRow = new LocalResponse(image,uid);
  singleRowArrayList.add(singleRow);
  }
  if (singleRowArrayList.size()==0){
  //empty.setVisibility(View.VISIBLE);
  recyclerView.setVisibility(View.GONE);
  }else {
  LocalDataBaseAdapter localDataBaseResponse = new LocalDataBaseAdapter(getContext(), singleRowArrayList, db, myDatabase);
  recyclerView.setAdapter(localDataBaseResponse);
  }


  }
  }

الخطوة 10 : افتح res -> layout -> xml أو ( Local_database_items.xml )

هذه هي الطريقة التي ستبدو بها عناصر Local DataBase RecyclerView هنا ، لقد استخدمت CardView حيث استخدمت ImageView لإظهار صورة ، كما استخدمنا صورة أخرى ImageView عند النقر عليها سيتم حذف صورتك من DataBase.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical">
  <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/cardView"
  android:layout_width="match_parent"
  android:layout_height="120dp"
  android:layout_margin="5dp"
  android:background="?attr/selectableItemBackground"
  android:clickable="true"
  android:elevation="5dp"
  android:focusable="true"
  android:foreground="?android:attr/selectableItemBackground"
  app:cardCornerRadius="5dp"
  android:visibility="visible">
  <RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="120dp"
  android:background="@color/color_white">
  <ImageView
  android:id="@+id/newsImage"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:scaleType="centerCrop"/>
  <ImageView
  android:id="@+id/delete"
  android:layout_width="wrap_content"
  android:layout_height="@dimen/_35sdp"
  android:layout_alignParentRight="true"
  android:padding="@dimen/_4sdp"
  android:src="@drawable/delete_icon"
  android:tint="#C7C7C7"/>

  </RelativeLayout>
  </android.support.v7.widget.CardView>
  </LinearLayout>

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

لقد استخدمت هنا طريقتين ، إحداهما getBitmapFromEncodedString (String encodedString) تستخدم لفك تشفير فئة Base64 إلى مصفوفة بايت ثم نستخدم مجموعة البايت هذه لتحويل Bitmap decodedByte. ثانيًا ، يتم حذف البيانات (الموضع النهائي النهائي ، ArrayList singleRowArrayList النهائي) وتستخدم هذه الطريقة لحذف البيانات من موضع معين في قاعدة البيانات. يمكننا حذف الصفوف المحددة من قاعدة البيانات باستخدام جملة WHERE مع استعلام DELETE ، وإلا فسيتم حذف جميع السجلات.

import android.content.Context;
  import android.content.DialogInterface;
  import android.database.sqlite.SQLiteDatabase;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.support.annotation.NonNull;
  import android.support.v7.app.AlertDialog;
  import android.support.v7.widget.RecyclerView;
  import android.util.Base64;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ImageView;
  import com.squareup.picasso.Picasso;

  import java.util.ArrayList;

  public class LocalDataBaseAdapter extends RecyclerView.Adapter {
  Context context;
  ArrayList singleRowArrayList;
  SQLiteDatabase db;
  DataBaseHandler myDatabase;
  public LocalDataBaseAdapter(Context context, ArrayList singleRowArrayList, SQLiteDatabase db, DataBaseHandler myDatabase) {
  this.context = context;
  this.singleRowArrayList = singleRowArrayList;
  this.db = db;
  this.myDatabase = myDatabase;
  }

  @NonNull
  @Override
  public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
  View view = LayoutInflater.from(context).inflate(R.layout.local_database_items, null);
  MyViewHolder myViewHolder = new MyViewHolder(view);
  return myViewHolder;
  }

  @Override
  public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, final int i) {
  myViewHolder.newsImage.setImageBitmap(getBitmapFromEncodedString(singleRowArrayList.get(i).image));
  myViewHolder.delete.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  deletedata(i,singleRowArrayList);
  }
  });
  }

  @Override
  public int getItemCount() {
  return singleRowArrayList.size();
  }

  class MyViewHolder extends RecyclerView.ViewHolder {
  ImageView newsImage,delete;

  public MyViewHolder(@NonNull View itemView) {
  super(itemView);
  newsImage = (ImageView) itemView.findViewById(R.id.newsImage);
  delete = (ImageView) itemView.findViewById(R.id.delete);
  }
  }

  public void deletedata(final int position, final ArrayList singleRowArrayList){
  new AlertDialog.Builder(context)
  .setIcon(R.drawable.defaultimage)
  .setTitle("Delete result")
  .setMessage("Are you sure you want delete this result?")
  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
  /* This is where deletions should be handled */
  myDatabase.deleteEntry(singleRowArrayList.get(position).getUid());
  singleRowArrayList.remove(position);
  notifyItemRemoved(position);
  notifyDataSetChanged();
  myDatabase.close();
  //((MainActivity) context).loadFragment(new LocalFragment(), true);

  }

  })
  .setNegativeButton("No", null)
  .show();
  }

  private Bitmap getBitmapFromEncodedString(String encodedString){

  byte[] arr = Base64.decode(encodedString, Base64.URL_SAFE);

  Bitmap img = BitmapFactory.decodeByteArray(arr, 0, arr.length);

  return img;

  }
  }

المخرجات  :

الآن قم بتشغيل التطبيق وستتمكن من النقر فوق الصورة بجهازك عن طريق النقر فوق SaveImage وستتمكن من رؤيتها لاحقًا بالنقر فوق ViewImage آخر ، ويمكنك أيضًا حذف الصور التي لا تريد تخزينها.

Camera Tutorial Example In Android Studio

كيفية إنشاء قائمة GridView وإضافة صور من الاستديو                                                                        

الان سوف نقوم بعمل قائمة مثل الlistView ولكن بشكل شبكة و تسمى GridView وهي مفيدة جدا في التعامل مع الصور مثلا اذا كنت تريد عرض قائمة من الصور بشكل شبكة فالGridView هي الحل الأمثل  .

التطبيق  سوف يحتوي في الاكتيفيتي الرئيسية على Button  و GridView  والاكتيفيتي الأخرى سوف تحتوي على زر لفتح معرض الصور وبعد اختيار الصورة والعودة إلى الاكتيفيتي الرئيسية سوف تظهر الصورة في القائمة .

 قم بإنشاء كلاس باسم Photos عن طريق New > JavaClass  (سوف أشرح وظيفته لاحقا) :

  public class Photos {

  Uri photo_uri;
  String Photo_name;

  public Uri getPhoto_uri() {
  return photo_uri;
  }

  public void setPhoto_uri(Uri photo_uri) {
  this.photo_uri = photo_uri;
  }

  public String getPhoto_name() {
  return Photo_name;
  }

  public void setPhoto_name(String photo_name) {
  Photo_name = photo_name;
  }
  }

xml custom_photo_gallery : وهذه سوف يتم عرضها في كل item في ال gridView مثل الليست فيو

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical" android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:padding="1dp">

  <ImageView
  android:layout_width="100dp"
  android:layout_height="100dp"
  android:id="@+id/mPhoto" />

  <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/mPhotoName"
  android:layout_marginTop="5dp"
  android:textSize="20sp"
  android:textColor="#5f0042"
  android:text="Image" />
  </LinearLayout>
كود ال xml للاياوت الأكتيفيتي الرئيسية activity_grid_list_view :
  <RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="wrap_content"
  android:layout_height="match_parent"
  tools:context="com.example.yaser.galleryexamples.GridListView">

  <GridView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:clickable="true"
  android:numColumns="auto_fit"
  android:id="@+id/photos_list"
  android:layout_below="@+id/add_photo"
  android:columnWidth="100dp"
  android:verticalSpacing="5dp"
  android:stretchMode="columnWidth"></GridView>

  <Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Add photo"
  android:id="@+id/add_photo"
  android:layout_alignParentTop="true"
  android:layout_centerHorizontal="true" />


  </RelativeLayout>

الان في الاكتيفيتي الرئيسية سوف نضع كود فتح الأكتيفيتي الأخرى باستخدام دالة onActivityResult لكي نستقبل الصورة من الاكتفيتي الثانية ونضعها في القائمة ,ولقد قمنا بشرح onActivityResult    

قمت بتسمية الأكتيفيتي الرئيسية بGridListView :

  public class GridListView extends AppCompatActivity {

  Button addPhoto;
  GridView photosGridList;
  ArrayList<Photos> photos = new ArrayList<>();
  final int REQUEST_PHOTO = 1 ;
  PhotosAdapter photo_adapter;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_grid_list_view);

  photosGridList = (GridView)findViewById(R.id.photos_list);
  photo_adapter = new PhotosAdapter(GridListView.this,photos);
  photosGridList.setAdapter(photo_adapter);

  addPhoto = (Button)findViewById(R.id.add_photo);
  addPhoto.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  startActivityForResult(new Intent(GridListView.this, SelectPhoto.class), REQUEST_PHOTO);
  }
  });
  }
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if(resultCode == RESULT_OK ){
  if(requestCode == REQUEST_PHOTO){
  Photos photo = new Photos();
  photo.setPhoto_uri(data.getData());
  photo.setPhoto_name(data.getStringExtra("photo_name"));
  photos.add(photo);
  photo_adapter = new PhotosAdapter(GridListView.this,photos);
  photosGridList.setAdapter(photo_adapter);
  }
  }else{
  Toast.makeText(GridListView.this,"error",Toast.LENGTH_SHORT).show();
  }
  }
  class PhotosAdapter extends BaseAdapter{
  List<Photos> mPhotos;
  Context mContext;

  public PhotosAdapter(Context context, ArrayList<Photos> photos){
  this.mPhotos = photos;
  this.mContext = context;
  }
  @Override
  public int getCount() {
  return mPhotos.size();
  }
  @Override
  public Object getItem(int position) {
  return mPhotos.get(position);
  }
  @Override
  public long getItemId(int position) {
  return 0;
  }
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
  ViewHolder holder = null;

  if(convertView == null){
  LayoutInflater inflater = LayoutInflater.from(GridListView.this);
  convertView = inflater.inflate(R.layout.custom_photo_gallery,null);

  holder = new ViewHolder();
  holder.photo = (ImageView) convertView.findViewById(R.id.mPhoto);
  holder.photo_name = (TextView) convertView.findViewById(R.id.mPhotoName);
  convertView.setTag(holder);
  }else{
  holder = (ViewHolder)convertView.getTag();
  }
  Photos photo = mPhotos.get(position);
  Picasso.with(mContext).load(photo.getPhoto_uri()).resize(300,300).centerCrop().into(holder.photo);
  holder.photo_name.setText(photo.getPhoto_name());
  return convertView;
  }
  class ViewHolder {
  ImageView photo;
  TextView photo_name;
  }
  }

 في البداية عرفنا اوبجكت من gridView وقمنا باعطائه الاي دي الخاص به في الاون كريت بعدها قمنا بإنشاء اوبجكت من كلاس الأدابتر وأعطيناه في الباراميتر الأول Context والثاني ال ArrayList والتي تتكون من Objects من الكلاس Photos وكل اوبجكت واحد يمثل صورة واحدة ,بعدها نعين الادابتر لل GridView  ,وفي حدث onClick للزر  نقوم بفتح أكتيفيتي  SelectPhoto  ونستعمل startActivityForResult لكي نستقبل الصورة بعد اختيارها , في دالة onActivityResult  نقوم بالبداية التأكد من الResultCode  و requestCode  كما تعلمنا سابقا ,, بعدها ننشئ اوبجكت من كلاس  Photos ونعين ال  photo_uri وال photo_name عن طريق دالة  set  وهي تقوم بتعيين المتغير كما وضعت في الباراميتر .. أي انه الآن أصبح لدينا اوبجكت يحتوي علىUri الصورة واسم الصورة وبعدها نقوم بإضافته إلى ال ArrayList .

قم بإنشاء اكتيفيتي  باسم SelectPhoto (أو أي اسم اخر ولكن لا تنسى تغييره عند استدعاء الاكتيفيتي )

 SelectPhoto :

  public class SelectPhoto extends AppCompatActivity {

  Button upload,OK;
  ImageView uploadedPhoto;
  Uri photo_uri;
  EditText photoName;
  String name;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_select_photo);

  photoName = (EditText)findViewById(R.id.photoname);
  OK = (Button)findViewById(R.id.ok);
  OK.setVisibility(View.GONE);
  upload = (Button)findViewById(R.id.uploadPhoto);
  uploadedPhoto = (ImageView)findViewById(R.id.uploadedPhoto);

  upload.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
  startActivityForResult(Intent.createChooser(i,"select your photo"),1);
  }
  });
  OK.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  Intent photo = new Intent();
  photo.setData(photo_uri);
  if(!photoName.getText().toString().equals("")) {
  name = photoName.getText().toString();
  }else{
  name = "";
  }
  photo.putExtra("photo_name", name);
  setResult(RESULT_OK, photo);
  finish();
  }
  });
  }
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if(requestCode == 1 && resultCode == RESULT_OK){
  photo_uri = data.getData();
  if(photo_uri.getPath() != null) {
  Picasso.with(Gallery_main.this).load(photo_uri).resize(300, 300).centerCrop().into(uploadedPhoto);
  OK.setVisibility(View.VISIBLE);
  }     
  }
  }

كود xml :

  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
  android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:orientation="vertical" tools:context=".Gallery_main"
  android:weightSum="1"&gt;

  &lt;TextView android:text="@string/help1" android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/textView" /&gt;

  &lt;Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="upload "
  android:id="@+id/uploadPhoto"
  android:layout_below="@+id/textView"
  android:layout_centerHorizontal="true"
  android:layout_gravity="center_horizontal" /&gt;

  &lt;ImageView
  android:layout_width="150dp"
  android:layout_height="150dp"
  android:id="@+id/uploadedPhoto"
  android:layout_below="@+id/textView"
  android:layout_toStartOf="@+id/uploadPhoto"
  android:layout_toLeftOf="@+id/uploadPhoto"
  android:layout_alignBottom="@+id/uploadPhoto"
  android:layout_gravity="center_horizontal" /&gt;

  &lt;EditText
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:id="@+id/photoname"
  android:layout_gravity="center_horizontal"
  android:hint="اكتب هنا أي اسم للصورة" /&gt;

  &lt;Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="OK"
  android:id="@+id/ok"
  android:layout_gravity="center_horizontal" /&gt;

  &lt;/LinearLayout&gt;

اللاياوت تحتوي على زرين وصورة و editText  عند الضغط على الزر الأول يفتح معرض الصور وبعدها في دالة onActivityResult نقوم بأخذ ال Uri من ال data وباستخدام مكتبة بيكاسو نعين الصورة لل ImageView   وعند الضغط على الزر الثاني   ننشئ انتنت جديد ونعين الداتا الخاصة به عن طريق setData  لنضع ال Uri الخاص بالصورة التي اختارها المستخدم ثم نأخذ ما كتب في ال  EditText ونستخدم  putExtra لتمرير قيمة ال  Text إلى الأكتيفيتي الأولى

دالة setResult نضع فيها  RESULT_OK و  الانتنت الذي نريد تمريره بعدها بدالة finish ننهي هذه الاكتيفيتي للعودة للاكتفيتي السابقة .

نعود لonActivityResult في GridListView  وكما ترى data.getData هي ال uri الذي وضعناه في دالة setData في اكتيفيتي SelectPhoto و photo_name هو الkey لقيمة ما كتب في ال EditText,  بعد اضافة الأوبجكت للArrayList ننشئ اوبجكت للأدابتر وسوف يقوم الأدابتر بعرض ال objects الموجودة في ال ArrayList على شكل شبكة في ال GridView

ما يهم في كلاس الأدابتر هو دالة getView في البداية نقوم باستخدام ال inflater بتعيين اللاياوت التي تظهر في كل عنصر وهي custom_photo_gallery أي أن كل عنصر سوف يحتوي على صورة و textView بعدها ننشئ اوبجكت من كلاس ViewHolder  وهو يحتوي على ال ImageView ,, TextView ثم نقوم بإعطائهما ال Id ,

دالة  setTag تأخذ باراميتر واحد يمكن أن يكون أي اوبجكت وبما أننا أعطيناها ال holder فسيصبح   convertView يحتوي على id  الخاص بال views  لذلك لن نحتاج إلى انشاء اوبجكت جديد من كلاس ViewHolder في كل مرة نضيف صورة , لأن if لن تنفذ إلا في المرة الأولى من استدعاء getView  وفي داخل ال else نقوم بتعيين ال holder إلى getTag وسترجع هذه الدالة holder الذي يحتوي على id لذلك لن نحتاج إلى إعادة تعيين ال id للصورة والتيكست فيو في كل مرة تستدعى getView وذلك سيسرع عملية عرض الصور ,

(Photos photo = mPhotos.get(position

mPhotos هي ArrayList وتحتوي على objects من نوع Photos ولكي نحصل على الصورة الحالية ننشئ اوبجكت من Photos  ونستدعي دالة get ثم نمرر ال position لل row (يعني موقع الصورة في القائمة ) ليصبح الآن photo يحتوي على معلومات الصورة

   كيفية فتح تطبيق الكاميرا المدمج بالهاتف والتقاط صورة 

 سوف نتعلم كيفية فتح تطبيق الكاميرا المدمج بالهاتف والتقاط صورة ثم اضافتها إلى القائمة GridView التي قمنا بصنعها في  .

في البدادية يجب إضافة صلاحيات فتح تطبيق الكاميرا بداخل ملف AndroidManifest.xml :

  <uses-permission android:name="android.permission.CAMERA" />
  <uses-feature android:name="android.hardware.camera" />

ثم قم بإنشاء زر جديد بلاويت الخاصة بأكتيفيتي SelectPhoto بجانب زر upload الذي أنشأناه لأخذ صورة من الاستديو في الدرس السابق , الآن سوف ننشئ زر آخر لفتح تطبيق الكاميرا

كود xml للزر :

  <Button
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="TakePhoto"
  android:id="@+id/takephoto"
  android:layout_gravity="center_vertical"
  android:layout_marginLeft="50dp" />

سوف نقوم بتعيين onClick للزر بداخل اكتيفيتي SelectPhoto :

  openCamera = (Button)findViewById(R.id.takephoto);

  openCamera.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {

  }
  });

لفتح الكاميرا سوف نستخدم طريقة مماثلة للتي استخدمناها لفتح الاستديو , أولا ننشئ انتنت ونقوم بوضع مسار فتح الكاميرا داخل البارامتر , وبعدها نستخدم startActivtyForResult لفتح الانتنت واستقبال الصورة في onActivityResult 

ضع هذا الكود بداخل حدث onClick للزر :

  Intent openCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  startActivityForResult(openCamera,2);

وبداخل onActivityResult  فقط قم بتغييرر الأمر داخل if :

  if (requestCode == 1 ||requestCode == 2 && resultCode == RESULT_OK) {
  photo_uri = data.getData();
  if (photo_uri.getPath() != null) {
  Picasso.with(Gallery_main.this).load(photo_uri).resize(300, 300).centerCrop().into(uploadedPhoto);
  OK.setVisibility(View.VISIBLE);
  }
  }

لاحظ أنني استعملت requestCode آخر لتمييز فتح الكاميرا عن الاستديو , لكن بما انه كود جلب الصورة من الكاميرا بعد التقاتها هو نفسه كود جلب الصورة من الاستديو بعد اختيارها , لذلك لن نحتاج إلى if أخرى

جرب تشغيل البرنامج الآن والتقط صورة  الآن .