I'm building a video player app, when I scroll fast my video list in any folder app crashes and goest to MainActivity (Previous activity) where folderList
my code is posted below.
please anyone know how to fix it please guide me
videoFilesActivity
package com.example.rgplayer.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;
import com.example.rgplayer.models.MediaFiles;
import com.example.rgplayer.R;
import com.example.rgplayer.adapters.VideoFilesAdapter;
import java.util.ArrayList;
public class VideoFilesActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
public static final String MY_PREF = "my pref";
RecyclerView recyclerView;
private ArrayList<MediaFiles> videoFilesArrayList = new ArrayList<>();
static VideoFilesAdapter videoFilesAdapter;
String folder_name;
String sortOrder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_files);
folder_name = getIntent().getStringExtra("folderName");
getSupportActionBar().setTitle("folderName");
recyclerView = findViewById(R.id.videos_rv);
SharedPreferences.Editor editor = getSharedPreferences(MY_PREF, MODE_PRIVATE).edit();
editor.putString("playlistFOlderName", folder_name);
editor.apply();
showVideoFiles();
}
private void showVideoFiles() {
videoFilesArrayList = fetchMedia(folder_name);
videoFilesAdapter = new VideoFilesAdapter(videoFilesArrayList, this, 0);
recyclerView.setAdapter(videoFilesAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this,
RecyclerView.VERTICAL,false));
videoFilesAdapter.notifyDataSetChanged();
}
private ArrayList<MediaFiles> fetchMedia(String folderName) {
SharedPreferences preferences = getSharedPreferences(MY_PREF, MODE_PRIVATE);
String sort_value = preferences.getString("sort", "abcd");
ArrayList<MediaFiles> videoFiles = new ArrayList<>();
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
if(sort_value.equals("sortName")) {
sortOrder = MediaStore.MediaColumns.DISPLAY_NAME+" ASC";
}else if (sort_value.equals("sortSize")){
sortOrder = MediaStore.MediaColumns.SIZE+" DESC";
} else if (sort_value.equals("sorDate")) {
sortOrder = MediaStore.MediaColumns.DATE_ADDED + " DESC";
}else {
sortOrder = MediaStore.Video.Media.DURATION+ " DESC";
}
String selection = MediaStore.Video.Media.DATA+" like?";
String[] selectionArg = new String[]{"%"+folderName+"%"};
Cursor cursor = getContentResolver().query(uri, null,
selection, selectionArg, sortOrder);
if (cursor!=null && cursor.moveToNext()) {
do {
@SuppressLint("Range") String id = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID));
@SuppressLint("Range") String title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE));
@SuppressLint("Range") String displayName = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME));
@SuppressLint("Range") String size = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.SIZE));
@SuppressLint("Range") String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DURATION));
@SuppressLint("Range") String path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
@SuppressLint("Range") String dateAdded = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED));
MediaFiles mediaFiles = new MediaFiles(id, title, displayName, size, duration, path,
dateAdded);
videoFiles.add(mediaFiles);
}while (cursor.moveToNext());
}
return videoFiles;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.video_menu, menu);
MenuItem menuItem = menu.findItem(R.id.search_video);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setOnQueryTextListener(this);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
SharedPreferences preferences = getSharedPreferences(MY_PREF, MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
int id = item.getItemId();
switch (id) {
case R.id.refresh_videos:
finish();
startActivity(getIntent());
break;
case R.id.sort_by:
AlertDialog.Builder alertdialog = new AlertDialog.Builder(this);
alertdialog.setTitle("Sort By");
alertdialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
editor.apply();
finish();
startActivity(getIntent());
dialog.dismiss();
}
});
String[] items = {"Name (A to Z)", "Size (Big to Small)", "Date (New to Old)",
"Length (Log to Short)"};
alertdialog.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch ( which){
case 0:
editor.putString("sort", "sortName");
break;
case 1:
editor.putString("sort", "sortSize");
break;
case 2:
editor.putString("sort", "sortDate");
break;
case 3:
editor.putString("sort", "sortLenght");
break;
}
}
});
alertdialog.create().show();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
String inputs = newText.toLowerCase();
ArrayList<MediaFiles> mediaFiles = new ArrayList<>();
for (MediaFiles media : videoFilesArrayList){
if (media.getTitle().toLowerCase().contains(inputs)){
mediaFiles.add(media);
}
}
VideoFilesActivity.videoFilesAdapter.updateVideoFiles(mediaFiles);
return true;
}
}
videoFilesAdapter
package com.example.rgplayer.adapters;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.MediaMetadataRetriever;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.annotation.GlideType;
import com.bumptech.glide.load.Transformation;
import com.example.rgplayer.models.MediaFiles;
import com.example.rgplayer.R;
import com.example.rgplayer.models.Utility;
import com.example.rgplayer.activities.VideoPlayerActivity;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
public class VideoFilesAdapter extends RecyclerView.Adapter<VideoFilesAdapter.ViewHolder> {
private ArrayList<MediaFiles> videoList;
private Context context;
BottomSheetDialog bottomSheetDialog;
private int viewType;
public VideoFilesAdapter(ArrayList<MediaFiles> videoList, Context context,int viewType) {
this.videoList = videoList;
this.context = context;
this.viewType = viewType;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.video_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, @SuppressLint("RecyclerView") int position) {
holder.videoName.setText(videoList.get(position).getDisplayName());
String size = videoList.get(position).getSize();
holder.videoSize.setText(android.text.format.Formatter.formatFileSize(context,
Long.parseLong(size)));
double milliSeconds = Double.parseDouble(videoList.get(position).getDuration());
holder.videoDuration.setText(Utility.timeConversion((long) milliSeconds));
Glide.with(context).load(new File(videoList.get(position).getPath()))
.into(holder.thumbnail);
if (viewType == 0) {
holder.menu_more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bottomSheetDialog = new BottomSheetDialog(context, R.style.BottomSheetTheme);
View bsView = LayoutInflater.from(context).inflate(R.layout.video_bs_layout,
v.findViewById(R.id.bottom_sheet));
bsView.findViewById(R.id.bs_play).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.itemView.performClick();
bottomSheetDialog.dismiss();
}
});
bsView.findViewById(R.id.bs_rename).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("Rename to");
EditText editText = new EditText(context);
String path = videoList.get(position).getPath();
final File file = new File(path);
String videoName = file.getName();
videoName = videoName.substring(0, videoName.lastIndexOf("."));
editText.setText(videoName);
alertDialog.setView(editText);
editText.requestFocus();
alertDialog.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (TextUtils.isEmpty(editText.getText().toString())) {
Toast.makeText(context, "Can't save file without name", Toast.LENGTH_SHORT).show();
return;
}
String onlyPath = file.getParentFile().getAbsolutePath();
String ext = file.getAbsolutePath();
ext = ext.substring(ext.lastIndexOf("."));
String newPath = onlyPath + "/" + editText.getText().toString() + ext;
File newFile = new File(newPath);
boolean rename = file.renameTo(newFile);
if (rename) {
ContentResolver resolver = context.getApplicationContext().getContentResolver();
resolver.delete(MediaStore.Files.getContentUri("external"),
MediaStore.MediaColumns.DATA + "=?", new String[]
{file.getAbsolutePath()});
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(newFile));
context.getApplicationContext().sendBroadcast(intent);
notifyDataSetChanged();
Toast.makeText(context, "Video Renamed", Toast.LENGTH_SHORT).show();
SystemClock.sleep(200);
((Activity) context).recreate();
} else {
Toast.makeText(context, "Progress has been failed", Toast.LENGTH_SHORT).show();
}
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.create().show();
bottomSheetDialog.dismiss();
}
});
bsView.findViewById(R.id.bs_share).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse(videoList.get(position).getPath());
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("video/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
context.startActivity(Intent.createChooser(shareIntent, "Share video via"));
bottomSheetDialog.dismiss();
}
});
bsView.findViewById(R.id.bs_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("Delete");
alertDialog.setMessage("Do you want to delete this video");
alertDialog.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Uri contentUri = ContentUris
.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
Long.parseLong(videoList.get(position).getId()));
File file = new File(videoList.get(position).getPath());
boolean delete = file.delete();
if (delete) {
context.getContentResolver().delete(contentUri, null, null);
videoList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, videoList.size());
Toast.makeText(context, "Video Deleted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Video can't be deleted", Toast.LENGTH_SHORT).show();
}
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
bottomSheetDialog.dismiss();
}
});
bsView.findViewById(R.id.bs_properties).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("Properties");
String one = "File: " + videoList.get(position).getDisplayName();
String path = videoList.get(position).getPath();
int indexOfPath = path.lastIndexOf("/");
String two = "Path: " + path.substring(0, indexOfPath);
String three = "Size: " + android.text.format.Formatter
.formatFileSize(context, Long.parseLong(videoList.get(position).getSize()));
String four = "Length: " + Utility.timeConversion((long) milliSeconds);
String namewithFormat = videoList.get(position).getDisplayName();
int index = namewithFormat.lastIndexOf(".");
String format = namewithFormat.substring(index + 1);
String five = "Format: " + format;
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
metadataRetriever.setDataSource(videoList.get(position).getPath());
String height = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
String six = "Resolution: " + width + "X" + height;
alertDialog.setMessage(one + "\n\n" + two + "\n\n" + three + "\n\n" + four + "\n\n" + five + "\n\n" + six);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
bottomSheetDialog.dismiss();
}
});
bottomSheetDialog.setContentView(bsView);
bottomSheetDialog.show();
}
});
} else {
holder.menu_more.setVisibility(View.GONE);
holder.videoName.setTextColor(Color.WHITE);
holder.videoSize.setTextColor(Color.WHITE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, VideoPlayerActivity.class);
intent.putExtra("position", position);
intent.putExtra("vide_title", videoList.get(position).getDisplayName());
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("videoArrayList", videoList);
intent.putExtras(bundle);
context.startActivity(intent);
if (viewType == 1) {
((Activity) context).finish();
}
}
});
}
@Override
public int getItemCount() {
return videoList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView thumbnail,menu_more;
TextView videoName, videoSize,videoDuration;
public ViewHolder(@NonNull View itemView) {
super(itemView);
thumbnail = itemView.findViewById(R.id.thumbnail);
menu_more = itemView.findViewById(R.id.vide_menu_more);
videoName = itemView.findViewById(R.id.video_name);
videoSize = itemView.findViewById(R.id.video_size);
videoDuration = itemView.findViewById(R.id.video_duration);
}
}
public void updateVideoFiles(ArrayList<MediaFiles> files){
videoList = new ArrayList<>();
videoList.addAll(files);
notifyDataSetChanged();
}
}
activity_video_files.xlm
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".activities.VideoFilesActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/videos_rv"
/>
</RelativeLayout>
The error I got
D/ActivityThread: add activity client record, r= ActivityRecord{6a97e6a token=android.os.BinderProxy@8d2ab03 {com.example.rgplayer/com.example.rgplayer.activities.VideoFilesActivity}} token= android.os.BinderProxy@8d2ab03
D/InputEventReceiver: dispatchInputInterval 0
W/HiTouch_HiTouchSensor: depended package hiTouch does n't exist!
I/HiTouch_HiTouchSensor: HiTouch restricted: system app HiTouch don't exist.
D/HiTouch_PressGestureDetector: onAttached, package=com.example.rgplayer, windowType=1, mHiTouchRestricted=true
W/System: A resource failed to call close.
D/DecorView: showOrHideHighlightView: hasFocus=false; winMode=1; isMrgNull=true
D/HwCustConnectivityManagerImpl: isBlockNetworkRequestByNonAis, INVALID_SUBSCRIPTION_ID
I/ConnectivityManager: requestNetwork and the calling app is: com.example.rgplayer
D/DecorView: showOrHideHighlightView: hasFocus=true; winMode=1; isMrgNull=true
W/InputMethodManager: startInputReason = 1
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'
D/skia: --- Failed to create image decoder with message 'unimplemented'