نلاحظ تواجد ماسح رمز الاستجابة السريعة في العديد من التطبيقات لقراءة بعض البيانات المفيدة مثل العناوين الإلكترونية أو المعلومات الشخصية (الإسم، رقم الهاتف، البريد الإلكتروني…). في هذا البرنامج التعليمي، سوف ننجز واجهة برمجة تطبيقات (Barcode) الموجودة في واجهة برمجة تطبيقات (Google Mobile Vision). يعد رمز الاستجابة السريعة الشكل الأكثر استعمالا لتواجده في العديد من التطبيقات.
في ما يلي، سنُطور تطبيقًا يفحص قيمة رمز (QR) من صورة نقطية وكذلك يكشف رمز (QR) من خلال كاميرا ويؤدي الإجراءات المتصلة بها.
نقوم بإنشاء تطبيق جديد، ثم الملفات التالية (انظر اسفل لمعرفة الكود و المسار):
- ScannedBarcodeActivity.java // activity_scan_barcode.xml
- PictureBarcodeActivity.java // activity_barcode_picture.xml
- EmailActivity.java // activity_email.xml
- ic_launcher_background.xml // ic_launcher_foreground.xml
الخطوة الأولى: وضع الكود التالي مكان الموجود داخل ملف (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 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"> <Button android:id="@+id/btnTakePicture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/take_barcode_picture" /> <Button android:id="@+id/btnScanBarcode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btnTakePicture" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/activity_horizontal_margin" android:text="@string/scan_barcode" /> </RelativeLayout>
- الخطوة الثانية: وضع الكود التالي مكان الموجود داخل ملف (MainActivity.java)
package com.yourname.barcodevisionapi; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener { Button btnTakePicture, btnScanBarcode; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); } private void initViews() { btnTakePicture = findViewById(R.id.btnTakePicture); btnScanBarcode = findViewById(R.id.btnScanBarcode); btnTakePicture.setOnClickListener(this); btnScanBarcode.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnTakePicture: startActivity(new Intent(MainActivity.this, PictureBarcodeActivity.class)); break; case R.id.btnScanBarcode: startActivity(new Intent(MainActivity.this, ScannedBarcodeActivity.class)); break; } } }
- الخطوة التالثة: وضع الكود التالي مكان الموجود داخل ملف (AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yourname.barcodevisionapi"> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".PictureBarcodeActivity" /> <activity android:name=".ScannedBarcodeActivity" /> <activity android:name=".EmailActivity" android:windowSoftInputMode="adjustPan" /> <meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="barcode" /> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> </application> </manifest>
- الخطوة الرابعة: وضع الكود التالي مكان الموجود داخل ملف (build.gradle)
apply plugin: 'com.android.application' android { compileSdkVersion 26 defaultConfig { applicationId "com.yourname.barcodevisionapi" minSdkVersion 16 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' implementation 'com.google.android.gms:play-services-vision:11.8.0' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' }
- الخطوة الخامسة: ضع لكل ملف الكود المشار إليه
app/src/main/res/layout/activity_scan_barcode.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/activity_horizontal_margin"> <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/btnAction" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_centerVertical="true" /> <TextView android:id="@+id/txtBarcodeValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="@dimen/activity_horizontal_margin" android:layout_marginStart="@dimen/activity_horizontal_margin" android:text="No Barcode Detected" android:textColor="@android:color/white" android:textSize="20sp" /> <Button android:id="@+id/btnAction" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="ADD CONTENT IN THE MAIL" /> </RelativeLayout>
app/src/main/java/com/yourname/barcodevisionapi/ScannedBarcodeActivity.java
package com.yourname.barcodevisionapi; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.SparseArray; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.vision.CameraSource; import com.google.android.gms.vision.Detector; import com.google.android.gms.vision.barcode.Barcode; import com.google.android.gms.vision.barcode.BarcodeDetector; import java.io.IOException; public class ScannedBarcodeActivity extends AppCompatActivity { SurfaceView surfaceView; TextView txtBarcodeValue; private BarcodeDetector barcodeDetector; private CameraSource cameraSource; private static final int REQUEST_CAMERA_PERMISSION = 201; Button btnAction; String intentData = ""; boolean isEmail = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan_barcode); initViews(); } private void initViews() { txtBarcodeValue = findViewById(R.id.txtBarcodeValue); surfaceView = findViewById(R.id.surfaceView); btnAction = findViewById(R.id.btnAction); btnAction.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (intentData.length() > 0) { if (isEmail) startActivity(new Intent(ScannedBarcodeActivity.this, EmailActivity.class).putExtra("email_address", intentData)); else { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(intentData))); } } } }); } private void initialiseDetectorsAndSources() { Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show(); barcodeDetector = new BarcodeDetector.Builder(this) .setBarcodeFormats(Barcode.ALL_FORMATS) .build(); cameraSource = new CameraSource.Builder(this, barcodeDetector) .setRequestedPreviewSize(1920, 1080) .setAutoFocusEnabled(true) //you should add this feature .build(); surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { try { if (ActivityCompat.checkSelfPermission(ScannedBarcodeActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { cameraSource.start(surfaceView.getHolder()); } else { ActivityCompat.requestPermissions(ScannedBarcodeActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { cameraSource.stop(); } }); barcodeDetector.setProcessor(new Detector.Processor<Barcode>() { @Override public void release() { Toast.makeText(getApplicationContext(), "To prevent memory leaks barcode scanner has been stopped", Toast.LENGTH_SHORT).show(); } @Override public void receiveDetections(Detector.Detections<Barcode> detections) { final SparseArray<Barcode> barcodes = detections.getDetectedItems(); if (barcodes.size() != 0) { txtBarcodeValue.post(new Runnable() { @Override public void run() { if (barcodes.valueAt(0).email != null) { txtBarcodeValue.removeCallbacks(null); intentData = barcodes.valueAt(0).email.address; txtBarcodeValue.setText(intentData); isEmail = true; btnAction.setText("ADD CONTENT TO THE MAIL"); } else { isEmail = false; btnAction.setText("LAUNCH URL"); intentData = barcodes.valueAt(0).displayValue; txtBarcodeValue.setText(intentData); } } }); } } }); } @Override protected void onPause() { super.onPause(); cameraSource.release(); } @Override protected void onResume() { super.onResume(); initialiseDetectorsAndSources(); } }
app/src/main/res/layout/activity_barcode_picture.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <ImageView android:id="@+id/imageView" android:layout_width="150dp" android:layout_height="150dp" android:layout_centerHorizontal="true" android:src="@mipmap/journaldev_logo" /> <TextView android:id="@+id/txtResultsHeader" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/imageView" android:layout_centerHorizontal="true" android:text="Results" android:textSize="18sp" android:textStyle="bold" /> <TextView android:id="@+id/txtResultsBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/txtResultsHeader" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/activity_horizontal_margin" android:gravity="center" /> <Button android:id="@+id/btnOpenCamera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="@dimen/activity_horizontal_margin" android:layout_marginTop="@dimen/activity_horizontal_margin" android:text="@string/open_camera" /> </RelativeLayout>
app/src/main/java/com/yourname/barcodevisionapi/PictureBarcodeActivity.java
package com.yourname.barcodevisionapi; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.FileProvider; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.util.SparseArray; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.vision.Frame; import com.google.android.gms.vision.barcode.Barcode; import com.google.android.gms.vision.barcode.BarcodeDetector; import java.io.File; import java.io.FileNotFoundException; public class PictureBarcodeActivity extends AppCompatActivity implements View.OnClickListener { Button btnOpenCamera; TextView txtResultBody; private BarcodeDetector detector; private Uri imageUri; private static final int REQUEST_CAMERA_PERMISSION = 200; private static final int CAMERA_REQUEST = 101; private static final String TAG = "API123"; private static final String SAVED_INSTANCE_URI = "uri"; private static final String SAVED_INSTANCE_RESULT = "result"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_barcode_picture); initViews(); if (savedInstanceState != null) { if (imageUri != null) { imageUri = Uri.parse(savedInstanceState.getString(SAVED_INSTANCE_URI)); txtResultBody.setText(savedInstanceState.getString(SAVED_INSTANCE_RESULT)); } } detector = new BarcodeDetector.Builder(getApplicationContext()) .setBarcodeFormats(Barcode.DATA_MATRIX | Barcode.QR_CODE) .build(); if (!detector.isOperational()) { txtResultBody.setText("Detector initialisation failed"); return; } } private void initViews() { txtResultBody = findViewById(R.id.txtResultsBody); btnOpenCamera = findViewById(R.id.btnOpenCamera); txtResultBody = findViewById(R.id.txtResultsBody); btnOpenCamera.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnOpenCamera: ActivityCompat.requestPermissions(PictureBarcodeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_CAMERA_PERMISSION: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { takeBarcodePicture(); } else { Toast.makeText(getApplicationContext(), "Permission Denied!", Toast.LENGTH_SHORT).show(); } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) { launchMediaScanIntent(); try { Bitmap bitmap = decodeBitmapUri(this, imageUri); if (detector.isOperational() && bitmap != null) { Frame frame = new Frame.Builder().setBitmap(bitmap).build(); SparseArray<Barcode> barcodes = detector.detect(frame); for (int index = 0; index < barcodes.size(); index++) { Barcode code = barcodes.valueAt(index); txtResultBody.setText(txtResultBody.getText() + "\n" + code.displayValue + "\n"); int type = barcodes.valueAt(index).valueFormat; switch (type) { case Barcode.CONTACT_INFO: Log.i(TAG, code.contactInfo.title); break; case Barcode.EMAIL: Log.i(TAG, code.displayValue); break; case Barcode.ISBN: Log.i(TAG, code.rawValue); break; case Barcode.PHONE: Log.i(TAG, code.phone.number); break; case Barcode.PRODUCT: Log.i(TAG, code.rawValue); break; case Barcode.SMS: Log.i(TAG, code.sms.message); break; case Barcode.TEXT: Log.i(TAG, code.displayValue); break; case Barcode.URL: Log.i(TAG, "url: " + code.displayValue); break; case Barcode.WIFI: Log.i(TAG, code.wifi.ssid); break; case Barcode.GEO: Log.i(TAG, code.geoPoint.lat + ":" + code.geoPoint.lng); break; case Barcode.CALENDAR_EVENT: Log.i(TAG, code.calendarEvent.description); break; case Barcode.DRIVER_LICENSE: Log.i(TAG, code.driverLicense.licenseNumber); break; default: Log.i(TAG, code.rawValue); break; } } if (barcodes.size() == 0) { txtResultBody.setText("No barcode could be detected. Please try again."); } } else { txtResultBody.setText("Detector initialisation failed"); } } catch (Exception e) { Toast.makeText(getApplicationContext(), "Failed to load Image", Toast.LENGTH_SHORT) .show(); Log.e(TAG, e.toString()); } } } private void takeBarcodePicture() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File photo = new File(Environment.getExternalStorageDirectory(), "pic.jpg"); imageUri = FileProvider.getUriForFile(PictureBarcodeActivity.this, BuildConfig.APPLICATION_ID + ".provider", photo); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, CAMERA_REQUEST); } @Override protected void onSaveInstanceState(Bundle outState) { if (imageUri != null) { outState.putString(SAVED_INSTANCE_URI, imageUri.toString()); outState.putString(SAVED_INSTANCE_RESULT, txtResultBody.getText().toString()); } super.onSaveInstanceState(outState); } private void launchMediaScanIntent() { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); mediaScanIntent.setData(imageUri); this.sendBroadcast(mediaScanIntent); } private Bitmap decodeBitmapUri(Context ctx, Uri uri) throws FileNotFoundException { int targetW = 600; int targetH = 600; BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; int scaleFactor = Math.min(photoW / targetW, photoH / targetH); bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; return BitmapFactory.decodeStream(ctx.getContentResolver() .openInputStream(uri), null, bmOptions); } }
app/src/main/res/layout/activity_email.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 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"> <Button android:id="@+id/btnSendEmail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/inBody" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/activity_horizontal_margin" android:text="@string/send_email" /> <TextView android:id="@+id/txtEmailAddress" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Email Address: " android:textStyle="bold" /> <EditText android:id="@+id/inSubject" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/txtEmailAddress" android:layout_centerHorizontal="true" android:ems="10" android:hint="Subject" /> <EditText android:id="@+id/inBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/inSubject" android:layout_centerHorizontal="true" android:ems="10" android:hint="Body" /> </RelativeLayout>
app/src/main/java/com/yourname/barcodevisionapi/mailActivity.java
package com.yourname.barcodevisionapi; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class EmailActivity extends AppCompatActivity implements View.OnClickListener { EditText inSubject, inBody; TextView txtEmailAddress; Button btnSendEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_email); initViews(); } private void initViews() { inSubject = findViewById(R.id.inSubject); inBody = findViewById(R.id.inBody); txtEmailAddress = findViewById(R.id.txtEmailAddress); btnSendEmail = findViewById(R.id.btnSendEmail); if (getIntent().getStringExtra("email_address") != null) { txtEmailAddress.setText("Recipient : " + getIntent().getStringExtra("email_address")); } btnSendEmail.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_EMAIL, new String[]{txtEmailAddress.getText().toString()}); intent.putExtra(Intent.EXTRA_SUBJECT, inSubject.getText().toString().trim()); intent.putExtra(Intent.EXTRA_TEXT, inBody.getText().toString().trim()); startActivity(Intent.createChooser(intent, "Send Email")); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnTakePicture: startActivity(new Intent(EmailActivity.this, PictureBarcodeActivity.class)); break; case R.id.btnScanBarcode: startActivity(new Intent(EmailActivity.this, ScannedBarcodeActivity.class)); break; } } }
app/src/main/res/drawable/ic_launcher_background.xml
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="108dp" android:height="108dp" android:viewportHeight="108" android:viewportWidth="108"> <path android:fillColor="#26A69A" android:pathData="M0,0h108v108h-108z" /> <path android:fillColor="#00000000" android:pathData="M9,0L9,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,0L19,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M29,0L29,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M39,0L39,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M49,0L49,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M59,0L59,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M69,0L69,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M79,0L79,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M89,0L89,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M99,0L99,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,9L108,9" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,19L108,19" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,29L108,29" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,39L108,39" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,49L108,49" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,59L108,59" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,69L108,69" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,79L108,79" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,89L108,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M0,99L108,99" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,29L89,29" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,39L89,39" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,49L89,49" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,59L89,59" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,69L89,69" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M19,79L89,79" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M29,19L29,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M39,19L39,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M49,19L49,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M59,19L59,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M69,19L69,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> <path android:fillColor="#00000000" android:pathData="M79,19L79,89" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8" /> </vector>
app/src/main/res/drawable-v24/ic_launcher_foreground.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="108dp" android:height="108dp" android:viewportHeight="108" android:viewportWidth="108"> <path android:fillType="evenOdd" android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" android:strokeColor="#00000000" android:strokeWidth="1"> <aapt:attr name="android:fillColor"> <gradient android:endX="78.5885" android:endY="90.9159" android:startX="48.7653" android:startY="61.0927" android:type="linear"> <item android:color="#44000000" android:offset="0.0" /> <item android:color="#00000000" android:offset="1.0" /> </gradient> </aapt:attr> </path> <path android:fillColor="#FFFFFF" android:fillType="nonZero" android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" android:strokeColor="#00000000" android:strokeWidth="1" /> </vector>
strings.xml
<resources> <string name="app_name">BarcodeVisionAPI</string> <string name="take_barcode_picture">Take Barcode Picture</string> <string name="scan_barcode">Scan Barcode</string> <string name="open_camera">OPEN CAMERA</string> <string name="send_email">SEND EMAIL</string> </resources>
الآن قم بتجربة التطبيق
بالتوفيق