user6265109 user6265109 - 5 months ago 52
Android Question

How to get and show the length of an array?

I want to create a folder for my app. For this permissions needs to be checked at run time. So when the user accepts the request I am creating the folder and initializing the listFile array with the number of files in the directory.

Also I have one asyncTask to get an events. So I am creating the main list inside onPostExecute method of an asyncTask.

In this main list I want to show the length of an listFile array. But It's crashing with a null pointer exception.

MainActivity :

public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,GetEventsAsyncTask.GetEvents {

private RecyclerView recyclerView;
private MainListAdapter mAdapter;
private List<MainList> mainLists = new ArrayList<>();


String folder_main = "MeaVita";
File dir = new File(Environment.getExternalStorageDirectory(),folder_main);

File[] listFile;
public int REQUEST_CODE_ASK_PERMISSIONS = 11;
public boolean permissionsAccepted;
private String userUsername;

public int PERMISSIONS_WRITE_EXTERNAL_STORAGE =10;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

sharedpreferences = getSharedPreferences("username",Context.MODE_PRIVATE);

userUsername = sharedpreferences.getString("UserUsername","No name defined");

GetEventsAsyncTask getEventsAsyncTask = new GetEventsAsyncTask(this,MainActivity.this,eventArrayList);
getEventsAsyncTask.execute(userUsername);

parent = (AppBarLayout) findViewById(R.id.view3);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

eventArrayList = new ArrayList<>();

checkFilePermissions();

recyclerView.setAdapter(new MainListAdapter(mainLists, new MainListAdapter.OnItemClickListener() {
@Override public void onItemClick(MainList item) {

if(item.getTitle().equals("Plan Event")) {
startActivity(new Intent(MainActivity.this, PlanEventActivity.class));
}
if(item.getTitle().equals("Events")) {
startActivity(new Intent(MainActivity.this, EventsListActivity.class));
}
if(item.getTitle().equals("Photos")) {
// checkFilePermissions();

sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

permissionsAccepted = sharedpreferences.getBoolean("permission",false);

if(dir.exists()) {

if (permissionsAccepted) {


if (listFile.length == 0) {


showAlert("No Images");

} else {

new MainActivity.SingleMediaScanner(MainActivity.this, listFile[0]);
}

}
}
else {

showAlert("No Folder");
}

}
if(item.getTitle().equals("Reminders")) {
startActivity(new Intent(MainActivity.this, RemindersActivity.class));
}
if(item.getTitle().equals("Chat")) {

}
if(item.getTitle().equals("Notes")) {
startActivity(new Intent(MainActivity.this, NotesActivity.class));
}
if(item.getTitle().equals("Notifications")) {
startActivity(new Intent(MainActivity.this, NotificationsActivity.class));
}
if(item.getTitle().equals("Profile")) {
startActivity(new Intent(MainActivity.this, ProfileActivity.class));
}
}
}));

RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());


}

public class SingleMediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {

private MediaScannerConnection mMs;
private File mFile;

public SingleMediaScanner(Context context, File f) {
mFile = f;
mMs = new MediaScannerConnection(context, this);
mMs.connect();
}

public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), null);
}

public void onScanCompleted(String path, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
mMs.disconnect();
}

}

private void checkFilePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWriteExternalStoragePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
}

}
}

@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (REQUEST_CODE_ASK_PERMISSIONS == 11) {

// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {


if (!dir.exists()) {
dir.mkdirs();
permissionsAccepted = true;
}

listFile = dir.listFiles();


SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean("permission",permissionsAccepted);
editor.apply();


if (listFile.length == 0) {
Toast.makeText(MainActivity.this, "The folder is empty.", Toast.LENGTH_SHORT).show();
}

else {

new MainActivity.SingleMediaScanner(MainActivity.this, listFile[0]);
}
// permission was granted, yay! Do the
// contacts-related task you need to do.

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(MainActivity.this, "Request Denied", Toast.LENGTH_SHORT).show();

}


// other 'case' lines to check for other
// permissions this app might request
}
}

private void prepareData() {



MainList mainList = new MainList("Plan Event","", R.drawable.plan);
mainLists.add(mainList);

mainList = new MainList("Events",String.valueOf(eventArrayList.size()), R.drawable.events);
mainLists.add(mainList);

mainList = new MainList("Photos",String.valueOf(listFile.length), R.drawable.phone);
mainLists.add(mainList);

mainList = new MainList("Reminders","20", R.drawable.remind);
mainLists.add(mainList);

mainList = new MainList("Chat","2", R.drawable.chat);
mainLists.add(mainList);

mainList = new MainList("Notes","2", R.drawable.notes);
mainLists.add(mainList);

mainList = new MainList("Notifications","20", R.drawable.remind);
mainLists.add(mainList);

mainList = new MainList("Profile","50%", R.drawable.user);
mainLists.add(mainList);

}
public void showAlert(String alert) {

Snackbar snackbar = Snackbar.make(parent, alert, Snackbar.LENGTH_LONG);
snackbar.show();
}
@Override
public void doPostExecute(ArrayList<Event> response) {

eventArrayList = response;
listFile = dir.listFiles();
prepareData();

}
}


Log :

06-29 22:40:46.322 30194-30194/com.example.siddhi.meavita E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.siddhi.meavita, PID: 30194
java.lang.NullPointerException: Attempt to get length of null array
at com.example.siddhi.meavita.Activities.MainActivity.prepareData(MainActivity.java:341)
at com.example.siddhi.meavita.Activities.MainActivity.doPostExecute(MainActivity.java:370)
at com.example.siddhi.meavita.AsyncTaskClasses.GetEventsAsyncTask.onPostExecute(GetEventsAsyncTask.java:107)
at com.example.siddhi.meavita.AsyncTaskClasses.GetEventsAsyncTask.onPostExecute(GetEventsAsyncTask.java:28)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.-wrap1(AsyncTask.java)


How and when to initialize the listFile array and when to call the prepareData method?

Please help. Stuck on this, very much new to this.
Thank you.

Answer

You are using method File.listFiles() to get the list of files from a directory.

listFile can be null

However, according to Docs, this method can return null

public File[] listFiles()
...
Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.

dir.listFile() may return null in following conditions:

  1. If dir does not reflects a directory (dir can be pointing to a file for example.. it is not your case)
  2. Any I/O error (like permission or any other failure during reading directory contents.

As you can see, you can not ensure that listFile is always different from null`... It can be null ocasionally. So, you should first check if listFile is null before read its properties/values.

null protection

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    listFile = dir.listFiles();
    ...
    if (listFile == null || listFile.length == 0) {
        Toast.makeText(MainActivity.this, "The folder is empty.", Toast.LENGTH_SHORT).show();
    } else {
        new MainActivity.SingleMediaScanner(MainActivity.this, listFile[0]);
    }
    ...
}

AND

private void prepareData() {
    ...
    if(listFile != null && listFile.length >= 0)
        mainList = new MainList("Photos",String.valueOf(listFile.length), R.drawable.phone);
    else
        mainList = new MainList("Photos", "0", R.drawable.phone);

    mainLists.add(mainList);
    ...
}