Wednesday, September 8, 2021

Decide Processor

 

https://laptopmedia.com/in/top-laptop-cpu-ranking/

11th-generation-intel-core-i5-processors list

https://ark.intel.com/content/www/us/en/ark/products/series/202985/11th-generation-intel-core-i5-processors.html

Rank-16

Intel® Core™ i5-11260H Processor Launched Q2'21 6 4.40 GHz 12 MB Intel® Smart Cache

10th-generation-intel-core-i5-processors list

https://ark.intel.com/content/www/us/en/ark/products/series/195732/10th-generation-intel-core-i5-processors.html

Rank-22

Intel® Core™ i5-11400H Processor Launched Q2'21 6 4.50 GHz 12 MB Intel® Smart Cache

Rank-26

Intel® Core™ i5-10500H Processor Launched Q4'20 6 4.50 GHz 2.50 GHz 12 MB Intel® Smart Cache



10th-generation-intel-core-i7-processors list

https://ark.intel.com/content/www/us/en/ark/products/series/195734/10th-generation-intel-core-i7-processors.html

Rank-17

Intel® Core™ i7-10875H Processor Launched Q2'20 8 5.10 GHz 2.30 GHz 16 MB Intel® Smart Cache

Rank-31

Intel® Core™ i7-10750H Processor Launched Q2'20 6 5.00 GHz 2.60 GHz 12 MB Intel® Smart Cache

Lenovo Legion 5 Core i7 10th Gen - (16 GB/512 GB SSD/Windows 10 Home/4 GB Graphics/NVIDIA GeForce GTX 1650/120 Hz) 15IMH05 Gaming Laptop  (15.6 Inch, Phantom Black, 2.3 KG

https://www.flipkart.com/lenovo-legion-5-core-i7-10th-gen-16-gb-512-gb-ssd-windows-10-home-4-graphics-nvidia-geforce-gtx-1650-120-hz-15imh05-gaming-laptop/p/itm799c8d74d9b0a?pid=COMG4BHEAZTYYSUM&affid=snikolovl

11th-generation-intel-core-i7-processors list

https://ark.intel.com/content/www/us/en/ark/products/series/202986/11th-generation-intel-core-i7-processors.html

Specs table

Intel Core i7-10875HIntel Core i7-10750H
ArchitectureComet Lake HComet Lake H
Cores / Threads8/166/12
Clock Speeds – Base/Boost2.30 – 5.10GHz2.60 – 5.00GHz
Cache16MB12MB
Lithography14nm14nm
TDP45W45W
Memory typeDDR4-2933MHzDDR4-2933MHz
Integrated GPUIntel UHD Graphics 630Intel UHD Graphics 630

No. of Cores/ Max Turbo Frequency/ Processor Base Frequency/ Cache



https://www.quora.com/Which-is-the-best-octa-core-16GB-RAM-laptop-which-I-can-use-for-programming-and-virtualization-and-costs-under-70K

https://laptopmedia.com/in/laptop-specs/lenovo-legion-5i-15-887/


https://www.investorsunderground.com/how-to-build-a-day-trading-computer/

Friday, April 10, 2020

My Quick Find Gallery (Part 5 - Share, Delete and Update Image)

12) Share Image
If your targetSdkVersion >= 24, then we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps.
Steps to replace file:// URI with content:// URI:
i) Add a FileProvider <provider> tag in AndroidManifest.xml under <application> tag:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
         <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.myfileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_provider_paths" />
         </provider>
    </application>
</manifest>
ii) Then create a file_provider_paths.xml file in res/xml folder:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="share" path="/" />
</paths>
iii) ShowPhoto.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
     switch (item.getItemId()) {
       case R.id.action_share:
         File file = new File(searchFilesPath.get(selectedImagePosition));
         Intent shareIntent = new Intent(Intent.ACTION_SEND);
         Uri picUri = FileProvider.getUriForFile(this, "com.myfileprovider", file);
         shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         shareIntent.setType("image/*");
         shareIntent.putExtra(Intent.EXTRA_STREAM, picUri);
         startActivity(Intent.createChooser(shareIntent, "Share with"));
         break;
       default:
         break;
     }
     return true;
}
13) Delete Image
Call function alert() on Delete Button in ShowPhoto.java
public void alert(){
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setTitle("Delete Photo");
        alertDialogBuilder
                .setMessage("are you sure you want to delete ?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        delete();
                    }
                })
                .setNegativeButton("No",new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();

}
public void delete(){
        File fdelete = new File(searchFilesPath.get(selectedImagePosition));
        if (fdelete.exists()) {
            if (fdelete.delete()) {
//Toast.makeText(this, "Successfully Deleted", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent();
                setResult(RESULT_OK, intent);
                finish();
            } else {
                Toast.makeText(this, "File not deleted", Toast.LENGTH_LONG).show();
            }
        }
}
14) Update Image
Call function alert() on Update Button in EditPhoto.java
public void alert(){
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setTitle("Update Tag or Photo");
        alertDialogBuilder
                .setMessage("are you sure you want to update ?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        update();
                    }
                })
                .setNegativeButton("No",new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();

}
public void update(){
        String tag=tag_editText.getText().toString();
        if(tag.matches("")) {
            Toast.makeText(this, "Please Enter Tag", Toast.LENGTH_LONG).show();
        }
        else {
            if(replaceToInternalStorage(bitmap,tag.trim())) {
                Intent intent = new Intent();
                setResult(RESULT_OK, intent);
                finish();
            }
            else {
                Toast toast = Toast.makeText(this, "File not updated", Toast.LENGTH_LONG);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
            }
        }
}
private boolean replaceToInternalStorage(Bitmap bitmapImage, String filename) {
        if (filename.equals(editFileName) && isImageChange == 0)
            return true;
        else if (!filename.equals(editFileName) && isImageChange == 0) {
            File oldFilePath = new File(editFilePath);
            File directory = oldFilePath.getParentFile();
            File newFilePath = new File(directory, filename + ".jpeg");
            int i = 2;
            while (newFilePath.exists()) {
                newFilePath = new File(directory, filename + "[" + i + "].jpeg");
                i++;
            }
            oldFilePath.renameTo(newFilePath);
            return true;
        }
        else if (isImageChange == 1) {
            if(delete(editFilePath)) {
                File mypath = new File(editFilePath);
                if(!filename.equals(editFileName)){
                    File oldFile = new File(editFilePath);
                    File directory = oldFile.getParentFile();
                    File newFile = new File(directory, filename + ".jpeg");
                    int i = 2;
                    while (newFile.exists()) {
                        newFile = new File(directory, filename + "[" + i + "].jpeg");
                        i++;
                    }
                    mypath=newFile;
                }
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(mypath);
                    bitmapImage.compress(Bitmap.CompressFormat.JPEG, 85, fos);
                    return true;
                } catch (Exception e) {
                    Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
                    return false;//e.printStackTrace();
                } finally {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
                        return false;//e.printStackTrace();
                    }
                }
            }
            else
                return false;
        }
        else
            return false;
}

My Quick Find Gallery (Part 4 - Show Image with Zoom, Drag and Slide Features)

11) Show Image with features of Zoom, Drag and Slide
Subtasks:
i) Get the set of images and selected image position from Parent Activity and show selected image in ImageView.
activity_show_photo.xml
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ShowPhoto">
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="0dp"
        android:layout_marginStart="0dp"
        android:layout_marginTop="8dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

ShowPhoto.java
ImageView selectedImage;
ArrayList<String> searchFilesPath;
ArrayList<String> searchFilesName;
int selectedImagePosition;
@Override
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_photo);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        selectedImage = (ImageView) findViewById(R.id.imageView);
        try {
            Intent intent = getIntent(); // get Intent which we set from Previous Activity
            selectedImagePosition = intent.getIntExtra("selectedImagePosition",0);
            searchFilesPath=intent.getStringArrayListExtra("searchFilesPath");
            searchFilesName=intent.getStringArrayListExtra("searchFilesName");
          //from file path
          Bitmap myBitmap = BitmapFactory.decodeFile(searchFilesPath.get(selectedImagePosition));
            selectedImage.setImageBitmap(myBitmap);
            getSupportActionBar().setTitle(searchFilesName.get(selectedImagePosition));
        }
        catch(Exception e) {
            Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
        }
}
ii) setOnTouchListener to ImageView for Zoom, Drag and Slide Features.
ShowPhoto.java
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_photo);
selectedImage = (ImageView) findViewById(R.id.imageView);
selectedImage.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
                ImageView view = (ImageView) v;
                view.bringToFront();
                viewTransformation(view, event);
                return true;
            }
        });
}
//====================================================================
   //ImageView Zoom-in and Zoom-Out
  //ZOOM (two finger) / ROTATION (two finger) / DRAG (Single finger)
//====================================================================
    float[] lastEvent = null;
    float d = 0f;
    float newRot = 0f;
    private boolean isZoomAndRotate;
    private boolean isOutSide;
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    private PointF start = new PointF();
    private PointF mid = new PointF();
    float oldDist = 1f;
    private float xCoOrdinate, yCoOrdinate;

    private int isPreviousMode = NONE;

    private void viewTransformation(View view, MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                // executed after the user touch on the screen
                xCoOrdinate = view.getX() - event.getRawX();
                yCoOrdinate = view.getY() - event.getRawY();
                start.set(event.getX(), event.getY());
                isOutSide = false;
                mode = DRAG;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > 10f) {
                    midPoint(mid, event);
                    mode = ZOOM;
                }
                lastEvent = new float[4];
                lastEvent[0] = event.getX(0);
                lastEvent[1] = event.getX(1);
                lastEvent[2] = event.getY(0);
                lastEvent[3] = event.getY(1);
                //d = rotation(event);
                break;
            case MotionEvent.ACTION_UP:
                // executed after the user release the touch on the screen
                isZoomAndRotate = false;
                if (mode == DRAG) {
                    float x = event.getX();
                    float y = event.getY();
                    if (isPreviousMode != ZOOM) {
                        if (start.x - x > 1) { //using start.x-x>1, not start.x>x because start.x>x executes in case of tapping also ()
                            selectedImagePosition = selectedImagePosition + 1;
                            if (selectedImagePosition <= maxImagePosition) {
selectedImage.setImageBitmap(BitmapFactory.decodeFile(searchFilesPath.get(selectedImagePosition)));
getSupportActionBar().setTitle(searchFilesName.get(selectedImagePosition));
                                isPreviousMode = NONE;
                            } else
                                selectedImagePosition = maxImagePosition;//when reach to last picture and thenafter move the finger again and again then selectedImagePosition values go to very high one by one therefore put the last picture index
                        } else if (x - start.x > 1) {
                            selectedImagePosition = selectedImagePosition - 1;
                            if (selectedImagePosition >= 0) {
selectedImage.setImageBitmap(BitmapFactory.decodeFile(searchFilesPath.get(selectedImagePosition)));
getSupportActionBar().setTitle(searchFilesName.get(selectedImagePosition));
                                isPreviousMode = NONE;
                            } else
                                selectedImagePosition = 0;
                        }
                    }
                }
            case MotionEvent.ACTION_OUTSIDE:
                isOutSide = true;
                mode = NONE;
                lastEvent = null;
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_MOVE:
                // executed when user move the finger on the screen
                if (!isOutSide) {
                    if (mode == DRAG) {
                        isZoomAndRotate = false;
                        if(isPreviousMode == ZOOM)
                            view.animate().x(event.getRawX() + xCoOrdinate).y(event.getRawY() + yCoOrdinate).setDuration(0).start();
                    }
                    if (mode == ZOOM && event.getPointerCount() == 2) {
                        float newDist1 = spacing(event);
                        if (newDist1 > 10f) {
                            float scale = newDist1 / oldDist * view.getScaleX();
                            view.setScaleX(scale);
                            view.setScaleY(scale);
                            isPreviousMode = ZOOM;
                        }
                        if (lastEvent != null) {
                            //newRot = rotation(event);
                            //view.setRotation((float) (view.getRotation() + (newRot - d)));
                        }
                    }
                }
                break;
        }
    }
    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double delta_y = (event.getY(0) - event.getY(1));
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (int) Math.sqrt(x * x + y * y);
    }
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

Wednesday, April 8, 2020

My Quick Find Gallery (Part 3 - Storage Permission & Browse, Tag and Save Image)

5) Storage Read/Write Permission

AndroidMainfest.xml

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

SplashScreen.java

 private static final int MY_WRITE_EXTERNAL_PERMISSION_CODE = 1;
    public boolean storagePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_WRITE_EXTERNAL_PERMISSION_CODE);
            }
            else
                return true;
        }
        return false;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == MY_WRITE_EXTERNAL_PERMISSION_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Intent intent = new Intent(SplashScreen.this, SearchActivity.class);
                startActivity(intent);
            }
            else {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("You need to give permission to access storage in order to work this app.");
                builder.setPositiveButton("GIVE PERMISSION", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.dismiss();
                        // Show permission request popup
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_WRITE_EXTERNAL_PERMISSION_CODE);
                        }
                    }
                });
                builder.setNegativeButton("CLOSE", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.dismiss();
                        finish();
                    }
                });
                builder.show();
            }
        }

    }

6) Browse Image from Gallery and Show Image in ImageView
Subtasks:
i) Set ImageView Property like that all different Scale of Images are perfectly fit into different type of phone screen.
activity_save_photo.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SavePhoto">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="0dp"
        android:layout_marginStart="0dp"
        android:layout_marginTop="8dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
ii) Open chooser Intent which show only Image Files
SavePhoto.java
private int PICK_IMAGE_REQUEST = 1;
    public void choosePhotoFromGallery(){
//        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//        intent.setType("image/*");
//        startActivityForResult(intent, PICK_IMAGE_REQUEST);
//        startActivityForResult(Intent.createChooser(intent, "Select Image"), PICK_IMAGE_REQUEST);

        Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
        getIntent.setType("image/*");

        Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        pickIntent.setType("image/*");

        Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

        startActivityForResult(chooserIntent, PICK_IMAGE_REQUEST);
    }
iii) Selected Image will be shown in ImageView
Subtasks 
a) Image will be get in form of URI from Image Chooser Intent.
b) We will find the path of image from Image URI
c) We will reduce the size of image but image quality will be almost same via ImageCompression class.
//iii)
SavePhoto.java
Uri selectedImageUri;
String picturePath;
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
//iii)a)
            selectedImageUri = data.getData();
//iii)b)
            picturePath = getPath(this, selectedImageUri );
            if(!picturePath.matches( "Not found")) {
                 try {
//iii)c)
                    ImageCompression ic= new ImageCompression(this);
                    bitmap=ic.compressImage(picturePath);
                    selectedImage.setImageBitmap(bitmap);
                } catch (Exception e) {
                    Toast.makeText(this, e.toString() , Toast.LENGTH_LONG).show();
                }
            }
            else
                Toast.makeText(this, "Image Path not found., Toast.LENGTH_SHORT).show();
        }

}
//iii)b)
public static String getPath(Context context, Uri uri ) {
        String result = null;
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver( ).query( uri, proj, null, null, null );
        if(cursor != null){
            if ( cursor.moveToFirst( ) ) {
                int column_index = cursor.getColumnIndexOrThrow( proj[0] );
                result = cursor.getString( column_index );
            }
            cursor.close( );
        }
        if(result == null) {
            result = "Not found";
        }
        return result;
}
//iii)c)
ImageCompression.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.ExifInterface;
import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by HP-HP on 03-07-2015.
 */
public class ImageCompression extends AsyncTask<String, Void, String> {
    private Context context;
    private static final float maxHeight = 1280.0f;
    private static final float maxWidth = 1280.0f;

    public ImageCompression(Context context){
        this.context=context;
    }
    @Override
    protected String doInBackground(String... strings) {
        if(strings.length == 0 || strings[0] == null)
            return null;
        //return compressImage(strings[0]);
        return "";
    }
    protected void onPostExecute(String imagePath){
        // imagePath is path of new compressed image.
    }

    public Bitmap compressImage(String imagePath) {
        Bitmap scaledBitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
        float imgRatio = (float) actualWidth / (float) actualHeight;
        float maxRatio = maxWidth / maxHeight;

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;
            }
        }
        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];
        try {
            bmp = BitmapFactory.decodeFile(imagePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }
        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;
        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
        if(bmp!=null){
            bmp.recycle();
        }
        ExifInterface exif;
        try {
            exif = new ExifInterface(imagePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
            } else if (orientation == 3) {
                matrix.postRotate(180);
            } else if (orientation == 8) {
                matrix.postRotate(270);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return scaledBitmap;

//        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
//        return out.toByteArray();
//        FileOutputStream out = null;
//        String filepath = getFilename();
//        try {
//            out = new FileOutputStream(filepath);
//
//            //write the compressed bitmap at the destination specified by filename.
//            scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//
//        return filepath;
    }
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        final float totalPixels = width * height;
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;
        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
        return inSampleSize;
    }
    public String getFilename() {
        File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
                + "/Android/data/"
                + context.getApplicationContext().getPackageName()
                + "/Files/Compressed");
        // Create the storage directory if it does not exist
        if (! mediaStorageDir.exists()){
            mediaStorageDir.mkdirs();
        }
        String mImageName="IMG_"+ String.valueOf(System.currentTimeMillis()) +".jpg";
        String uriString = (mediaStorageDir.getAbsolutePath() + "/"+ mImageName);;
        return uriString;
    }
}

7) Textbox in Action Bar, AutoCompleteList and Input Legal Character
menu_save.xml
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_tag_editText"
        android:title="Enter Tag"
        app:showAsAction="always"
        app:actionViewClass="android.widget.AutoCompleteTextView" />
    <item
        android:id="@+id/action_save"
        android:title="Save"
        app:showAsAction="always" />
</menu>

SavePhoto.java
private Menu menu;
AutoCompleteTextView tag_editText;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_save, menu);
        this.menu = menu;

tag_editText = (AutoCompleteTextView)menu.findItem(R.id.action_tag_editText).getActionView();
        tag_editText.getBackground().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
        tag_editText.setHint("Enter tag here...");
        tag_editText.requestFocus();
 ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_list_item_1,uniqueFileName);
        tag_editText.setAdapter(adapter);
        tag_editText.setDropDownBackgroundResource(R.color.White);
        tag_editText.setFilters(new InputFilter[] { filter });
        return true;
}
private String LEGAL_CHARACTERSET = " 1234567890().,'@#$&ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private InputFilter filter = new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source != null && !(LEGAL_CHARACTERSET.contains("" + source)) && source.length()==1){//source.length==1 because autocomplete selection was going to empty.
                return "";
            }
            return null;
        }
};

8) Save image in Storage. File name should be same as Tag Name. If Tag Name is repeating but File name can't be repeat therefor File name format should be Tag Name[count].jpeg
SavePhoto.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
case R.id.action_save:
                String tag=tag_editText.getText().toString();
                if(tag.matches("")) {
                    Toast toast = Toast.makeText(this, "Please Enter Tag", Toast.LENGTH_LONG);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
                else {
                    if (bitmap != null) {
                        if (saveToInternalStorage(bitmap, tag.trim())) {
                            Intent intent = new Intent();
                            intent.putExtra("savePhotoFileName", tag);
                            setResult(RESULT_OK, intent);
                            finish();
                        } else {
                            Toast toast = Toast.makeText(this, "File not saved", Toast.LENGTH_LONG);
                            toast.setGravity(Gravity.CENTER, 0, 0);
                            toast.show();
                        }
                    }  else {
                        Toast toast = Toast.makeText(this, "Please select image", Toast.LENGTH_LONG);
                        toast.setGravity(Gravity.CENTER, 0, 0);
                        toast.show();
                    }
                }
                break;
            default:
                break;
        }
        return true;

    }
private boolean saveToInternalStorage(Bitmap bitmapImage, String filename){
        File directory = new File(Environment.getExternalStorageDirectory().getPath(), getResources().getString(R.string.tag_image_directory_name));
        if (!directory.exists()) {
            directory.mkdirs();
        }
        File mypath=new File(directory,filename + ".jpeg");
        int i=2;
        while(mypath.exists()){
            mypath=new File(directory,filename + "["+ i + "].jpeg");
            i++;
        }
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(mypath);
            // Use the compress method on the BitMap object to write image to the OutputStream
            bitmapImage.compress(Bitmap.CompressFormat.JPEG, 85, fos);
            return true;
        } catch (Exception e) {
            Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
            return false;
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
                return false;
            }
        }
}

9) Back Arrow in Action Bar
SavePhoto.java
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_save_photo);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
           default:
                break;
        }
        return true;
}

10)i) Passing Variable from Parent Activity (SearchActivity) to Child Activity (SavePhoto)
SearchActivity.java
int SAVE_PHOTO_REQUEST_CODE=1;//it will use when i add photo and then comeback to this activity. Child activity passing value to parent activity.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_add_photo:
                Intent intent=new Intent(SearchActivity.this,SavePhoto.class);
                intent.putStringArrayListExtra("uniqueFileName",uniqueFileName);
                startActivityForResult(intent,SAVE_PHOTO_REQUEST_CODE);
                break;
    default:
                break;
        }
        return true;

}

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

      Intent intent = getIntent(); // get Intent which we set from Previous Activity
      uniqueFileName=intent.getStringArrayListExtra("uniqueFileName");

}
10)ii) Passing Variable from Child Activity (SavePhoto) to Parent Activity (SearchActivity)
Note: Child Activity should be open via startActivityForResult from Parent Activity
SavePhoto.java
Save Success Message as follows:
Intent intent = new Intent();
intent.putExtra("savePhotoFileName", tag);
setResult(RESULT_OK, intent);
finish();

SearchActivity.java
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == SAVE_PHOTO_REQUEST_CODE && resultCode == RESULT_OK) {
            String savePhotoFileName = data.getStringExtra("savePhotoFileName");
            search.setQuery(savePhotoFileName, true);
        }

}

Friday, April 3, 2020

My Quick Find Gallery (Part 2 - GridView to Show Images)


4) Show images in GridView and after clicking a image, move to Display Photo Screen

We show data in gridview via adapter. Adapter is a medium between Data and Gridview.

Data ( eg:Array)  ------>      Adapter  ------->     GridView

Subtasks:
i) Our Data i.e, image files present in a particular folder. All Files path of that folder will be stored in a string array variable (for transferring string array to adabter to Gridview):
    Subtasks:
   a) A list of files of a folder will be stored in a File Array variable
   b) Files in a File array variable will be sorted by modification date (new modified file comes first)
   c) Fetch Absolute path of files from Sorted File Array Variable and store into string array variable
   d) Fetch File Name without extension of files from Sorted File Array Variable and store into another string array variable
   e) Files Name is repeated in a string array therefor make a string array where all file names are unique. That will be use in suggestion list in search box.
ii) Actual Data which will be shown in GridView will come by three different actions of user. We will discuss in point iv) later. Now move to Adabter. Data transfer Array Data to Adabter via below line code:
     ImageCustomAdapter customAdapter = new ImageCustomAdapter(getApplicationContext(), ArrayList<String> variable name);
iii) Suppose Gridview will show 3 images in a row. Data transfer Adapter to GridView via this line code:               mImageGrid.setAdapter(customAdapter);

Note: Array Data --->  Adabter ------> GridView 
public void showImageInGrid(ArrayList<String> imagesPath){
      ImageCustomAdapter customAdapter = new ImageCustomAdapter(getApplicationContext(),imagesPath);
      mImageGrid.setAdapter(customAdapter);
    }
iv) GridView displays images when
   a) click the Show All Button:  All Images will show
   b) File Name is selected from suggestion list of search box and then click the search button: Suggestion List File Name matches Images will show
   c) Random file name enter in search box and then click the search button: Random File Name contains Images will show
Note: Text Change in Search Box should not searched because communication break to writing in search box due to system searching  & showing image files in grid view after each letter typing in search box, make system inconstancy state
v) GridView Item Click event

SearchActivity.java

ArrayList<String> allFilePath;// list of all file paths
ArrayList<String> allFileName;// list of all file name
ArrayList<String> uniqueFileName;// list of unique file name without extension

public void getAllFilesPathAndName() {
        allFilePath = new ArrayList<String>();
        allFileName = new ArrayList<String>();
        try {
//i)a)
            //path to /internal storage/ERS/0/my directory
            File directory = new File(Environment.getExternalStorageDirectory().getPath(), getResources().getString(R.string.tag_image_directory_name));
            if (directory.isDirectory()) {
                File[] listFile = directory.listFiles();
//i)b)
                Arrays.sort(listFile, new Comparator<File>() {
                    @Override
                    public int compare(File a, File b) {
                        if(a.lastModified() < b.lastModified() )
                            return 1;
                        if(a.lastModified() > b.lastModified() )
                            return -1;
                        return 0;
                    }
                });
//i)c)&d)
                for (int i = 0; i < listFile.length; i++) {
                    allFilePath.add(listFile[i].getAbsolutePath());
                    allFileName.add(getFileNameWithoutExtension(listFile[i].getName()));
                }
            }
//i)e)
            List<String> allfilename =  this.allFileName;
            Set<String> uniquefilename = new HashSet<String>(allfilename);//unique filename
            this.uniqueFileName=new ArrayList<String>(uniquefilename);

        }
        catch(Exception e){
            Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
        }
    }
//i)d)
    public String getFileNameWithoutExtension(String fileName){
        String[] fileNameParts;
        if(fileName.contains("[")){
            fileNameParts = fileName.split("\\[");
            return fileNameParts[0];
        }
        else{
            int pos = fileName.lastIndexOf(".");//"\\." is not working
            return fileName.substring(0, pos);
        }
    }

//ii)
galleryitem.xml

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

    <ImageView
        android:id="@+id/thumbImage"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:scaleType="fitXY"
        android:layout_gravity="center_horizontal"/>
</LinearLayout>

ImageCustomAdapter.java

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import java.util.ArrayList;

public class ImageCustomAdapter extends BaseAdapter {

    Context mContext;
    ArrayList<String> mFileArray;// list of file paths
    LayoutInflater mInflater;
    public int selectedImage = 0;

    public ImageCustomAdapter(Context applicationContext, ArrayList<String> fileArray) {
        this.mContext = applicationContext;
        this.mFileArray = fileArray;
        mInflater = (LayoutInflater.from(applicationContext));
    }

    @Override
    public int getCount() {
        return mFileArray.size();
    }
    @Override
    public Object getItem(int i) {
        return null;
    }
    @Override
    public long getItemId(int i) {
        return 0;
    }

    @Override
    public View getView(int i, View convertView, ViewGroup viewGroup) {

        convertView = mInflater.inflate(R.layout.galleryitem, null); // inflate the layout
        ImageView icon = (ImageView) convertView.findViewById(R.id.thumbImage); // get the reference of ImageView
        Bitmap myBitmap = BitmapFactory.decodeFile(mFileArray.get(i));
        Bitmap thumbnail = ThumbnailUtils.extractThumbnail(myBitmap,300,300);
        //Bitmap scaled = Bitmap.createScaledBitmap(myBitmap, 100, 100, true);
        icon.setImageBitmap(thumbnail);
        return convertView;
    }

}

//iii)
activity_search.xml

<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SearchActivity">

    <GridView
        android:id="@+id/ImageGrid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:numColumns="3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />
 
</android.support.constraint.ConstraintLayout>.

//iv)
SearchActivity.java

@Override
public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
//iv)a)         
case R.id.action_show_all:
                search.setQuery("", false);//this is because when i am adding photo then search box has adding file name. when i click on show all button then should be it clear it.
                isSearchAction=1;//Show All
                if(getFilePathArray(isSearchAction,"")>0) {
                    showImageInGrid(searchFilesPath);////ByFilePathArrayStringAndImageCustomAdapter
                    search.clearFocus();
                }
                else {
                    mImageGrid.setAdapter(null);
                    emptyResult();
                }
                break;
            default:
                break;
        }
        return true;
    }

ArrayList<String> searchFilesPath;// list of filter files path
ArrayList<String> searchFilesName;// list of filter files name

public int getFilePathArray(int isSearchAction, String searchTag){

        searchFilesPath=new ArrayList<String>();
        searchFilesName=new ArrayList<String>();
//iv)a)
        if(isSearchAction==1) {//show all
            searchFilesPath=allFilePath;
            searchFilesName=allFileName;
        }
//iv)b)
else if(isSearchAction==2) {//autocomplete name
            for (int i = 0; i < allFileName.size(); i++) {
                if (allFileName.get(i).equalsIgnoreCase(searchTag)) {
                    searchFilesPath.add(allFilePath.get(i));
                    searchFilesName.add(allFileName.get(i));
                }
            }
        }
//iv)c)
else if(isSearchAction==3){//random name
            for (int i = 0; i < allFileName.size(); i++) {
                if (allFileName.get(i).toLowerCase().contains(searchTag.toLowerCase())) {
                    searchFilesPath.add(allFilePath.get(i));
                    searchFilesName.add(allFileName.get(i));
                }
            }
        } else{ }
        return searchFilesPath.size();
    }

public void showImageInGrid(ArrayList<String> searchFilesPath){ //ByFilePathArrayStringAndImageCustomAdapter
        mImageGrid.setAdapter(null);
        ImageCustomAdapter customAdapter = new ImageCustomAdapter(getApplicationContext(), searchFilesPath);
        mImageGrid.setAdapter(customAdapter);
    }

private void emptyResult() {
        Toast toast = Toast.makeText(this, "No image found", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }

//v)
SearchActivity.java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

mImageGrid = findViewById(R.id.ImageGrid);     
//GridView Item Click Event
        mImageGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(SearchActivity.this, ShowPhoto.class);
                intent.putExtra("selectedImagePosition", position);
                intent.putStringArrayListExtra("searchFilesPath",searchFilesPath);
                intent.putStringArrayListExtra("searchFilesName",searchFilesName);
                startActivity(intent); // start Intent
            }
        });
}