问题
I'm creating an application where I want to read data from external storage (i.e get list of files and folders similar to file explorer) I have written the code it works fine on an actual device but in android emulator it only gives path and name of external storage from
Environment.getExternalStorageDirectory()
But when I try to list files and folders using the file.listFiles() function in java it returns null even though there are folders and files in that directory, This works fine on an actual device, I have given permission and everything, I want it working on an emulator because I don't always have an access to an android device. I'm running it on an amd processor with hyper-v enabled on windows
These are my emulator details
Name: Pixel_2_API_R
CPU/ABI: Google Play Intel Atom (x86)
Path: C:\Users\Rohan\.android\avd\Pixel_2_API_R.avd
Target: google_apis_playstore [Google Play] (API level R)
Skin: pixel_2
SD Card: 512M
fastboot.chosenSnapshotFile: runtime.network.speed: full
hw.accelerometer: yes
hw.device.name: pixel_2
hw.lcd.width: 1080
image.androidVersion.codename: R
hw.initialOrientation: Portrait
image.androidVersion.api: 29
tag.id: google_apis_playstore
hw.mainKeys: no
hw.camera.front: emulated
avd.ini.displayname: Pixel 2 API R
hw.gpu.mode: auto
hw.ramSize: 1536
PlayStore.enabled: true
fastboot.forceColdBoot: no
hw.cpu.ncore: 4
hw.keyboard: yes
hw.sensors.proximity: yes
hw.dPad: no
hw.lcd.height: 1920
vm.heapSize: 256
skin.dynamic: yes
hw.device.manufacturer: Google
hw.gps: yes
hw.audioInput: yes
image.sysdir.1: system-images\android-R\google_apis_playstore\x86\
showDeviceFrame: yes
hw.camera.back: virtualscene
AvdId: Pixel_2_API_R
hw.lcd.density: 420
hw.arc: false
hw.device.hash2: MD5:55acbc835978f326788ed66a5cd4c9a7
fastboot.forceChosenSnapshotBoot: no
fastboot.forceFastBoot: yes
hw.trackBall: no
hw.battery: yes
hw.sdCard: yes
tag.display: Google Play
runtime.network.latency: none
disk.dataPartition.size: 6442450944
hw.sensors.orientation: yes
avd.ini.encoding: UTF-8
hw.gpu.enabled: yes
This is my code (It works fine on actual device)
package com.example.instantshare.UI.Activities;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.StatFs;
import com.example.instantshare.R;
import com.example.instantshare.UI.Models.FileItem;
import com.example.instantshare.UI.UIComponents.FileListRecyclerViewAdapter;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
public class FilePickerActivity extends AppCompatActivity {
private static final String TAG = "FilePickerActivity";
private final int REQUEST_CODE = 1;
private static final ArrayList<FileItem> list = new ArrayList<>();
private static Context context;
private static String headerPath = ""; // Holds the string shown in the header which contains the current path the user is viewing
private static String actualPath = ""; // Holds the file path (Not shown to user)
private static String currentFolder = "";
private static int folderState = 0; // Holds how much directories the user has clicked on if (1) taken to selection of internal storage and sd card
// View variables
static RecyclerView fileListRecyclerView;
static TextView folderNameTextView,filePathTextView;
static LinearLayout filePathHolder;
static Animation fadeUp,fadeInLeft,fadeOutRight,fadeIn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_picker);
init();
StatFs statfs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
Log.d(TAG, "onCreate: " + (statfs.getAvailableBytes() / 100000));
}
}
// Called initially to link all the ui and load all the variables
private void init(){
fileListRecyclerView = findViewById(R.id.file_list_recycler_view);
filePathTextView = findViewById(R.id.file_path_text_view);
folderNameTextView = findViewById(R.id.folder_name_text_view);
filePathHolder = findViewById(R.id.file_path_linear_layout);
fadeUp = AnimationUtils.loadAnimation(this,R.anim.fade_up);
fadeInLeft = AnimationUtils.loadAnimation(this,R.anim.fade_in_left);
fadeOutRight = AnimationUtils.loadAnimation(this,R.anim.fade_out_right);
fadeIn = AnimationUtils.loadAnimation(this,R.anim.fade_in);
context = FilePickerActivity.this;
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
}
}
}
else {
readFileInit();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_CODE:
{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
readFileInit();
}
else{
finish();
}
}
}
}
// Code to show Internal storage and sd card if mounted
private void readFileInit(){
headerPath = "";
actualPath = "";
currentFolder = "";
list.clear();
FileItem internalStorage = new FileItem("Internal Storage","","internal_storage","internal_storage", Environment.getExternalStorageDirectory().getAbsolutePath(),"",true,false,false);
list.add(internalStorage);
filePathTextView.setText(headerPath);
folderNameTextView.setText(currentFolder);
try {
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
File storage = Environment.getExternalStorageDirectory();
FileItem externalStorage = new FileItem(storage.getName(),"","external_storage","external_storage", storage.getAbsolutePath(),"",true,false,false);
Log.d(TAG, "readFileInit: " + externalStorage.getPath());
list.add(externalStorage);
}
}
catch (Exception e){
e.printStackTrace();
}
Log.d(TAG, "readFileInit: " + list.toString());
setupRecyclerView(list);
fileListRecyclerView.startAnimation(fadeUp);
}
public static void clickedItem(FileItem fileItem){
if (fileItem.getStorage() || fileItem.getDirectory()){
currentFolder =fileItem.getName();
folderState++;
headerPath = headerPath.trim();
headerPath += fileItem.getName() + "/";
if (fileItem.getName().equals("Internal Storage") || fileItem.getName().toLowerCase().equals("sdcard") ){
actualPath += fileItem.getPath() + "/";
}
else{
actualPath += fileItem.getName() + "/";
}
filePathTextView.setText(headerPath);
filePathTextView.startAnimation(fadeUp);
folderNameTextView.setText(currentFolder);
folderNameTextView.startAnimation(fadeUp);
File directory = new File(actualPath);
Log.d(TAG, "clickedItem: Path: " + fileItem.getPath() + "/");
File[] files = directory.listFiles();
Log.d(TAG, "clickedItem: " + Arrays.toString(files));
list.clear();
try {
if(files != null){
for(int i = 0; i < files.length; i++){
FileItem list_item = new FileItem();
File file = files[i];
Log.d(TAG, "clickedItem: " + file.getName());
list_item.setName(file.getName());
list_item.setDirectory(file.isDirectory());
list_item.setFile(file.isFile());
list_item.setStorage(false);
String[] date = new Date(file.lastModified()).toString().split(" ");
String dateToSet = date[1] + " " + date[2] + " " + date[0] + " " + date[5];
list_item.setLastModified(dateToSet);
list_item.setPath(file.getAbsolutePath());
if(file.isDirectory()){
list_item.setExtension("");
}
else{
if(file.getName().contains(".")){
String[] splittedValue = file.getName().split("\\.");
Log.d(TAG, "clickedItem: 1 " + Arrays.toString(splittedValue));
list_item.setExtension(splittedValue[splittedValue.length - 1]);
}
else{
list_item.setExtension(file.getName());
}
}
list_item.setType(getFileType());
list.add(list_item);
}
}
setupRecyclerView(list);
fileListRecyclerView.startAnimation(fadeIn);
}
catch (Exception e){
e.printStackTrace();
}
}
else{
return;
}
}
private static String getFileType(){
return "";
}
@Override
public void onBackPressed() {
Log.d(TAG, "onBackPressed: " + folderState);
if(folderState > 1){
folderState--;
renderView();
}
else if(folderState == 1){
readFileInit();
folderState--;
}
else{
super.onBackPressed();
}
}
private static void renderView(){
String[] newPathArr = headerPath.split(">",-1);
String[] newPathArr1 = actualPath.split("/",-1);
headerPath = "";
actualPath = "";
currentFolder="";
Log.d(TAG, "renderView: " + Arrays.toString(newPathArr));
Log.d(TAG, "renderView: " + Arrays.toString(newPathArr1));
for(int i = 0; i < newPathArr.length - 2; i++){
headerPath += newPathArr[i] + "/";
if(i == newPathArr.length - 3){
currentFolder = newPathArr[i];
}
}
for (int i = 0; i < newPathArr1.length - 2; i++){
actualPath += newPathArr1[i] + "/";
}
Log.d(TAG, "renderView: " + actualPath);
File file = new File(actualPath);
filePathTextView.setText(headerPath);
filePathTextView.startAnimation(fadeUp);
folderNameTextView.setText(currentFolder);
folderNameTextView.startAnimation(fadeUp);
File[] files = file.listFiles();
list.clear();
try {
if(files != null){
for(int i = 0; i < files.length; i++){
FileItem list_item = new FileItem();
File file1 = files[i];
Log.d(TAG, "clickedItem: " + file.getName());
list_item.setName(file1.getName());
if (folderState == 0){
list_item.setStorage(true);
list_item.setDirectory(false);
list_item.setFile(false);
}
else{
list_item.setDirectory(file1.isDirectory());
list_item.setFile(file1.isFile());
list_item.setStorage(false);
}
String[] date = new Date(file1.lastModified()).toString().split(" ");
String dateToSet = date[1] + " " + date[2] + " " + date[0] + " " + date[5];
list_item.setLastModified(dateToSet);
list_item.setPath(file.getAbsolutePath());
if(file.isDirectory()){
list_item.setExtension("");
}
else{
if(file.getName().contains(".")){
String[] splittedValue = file.getName().split("\\.");
Log.d(TAG, "clickedItem: 1 " + Arrays.toString(splittedValue));
list_item.setExtension(splittedValue[splittedValue.length - 1]);
}
else{
list_item.setExtension(file.getName());
}
}
list_item.setType(getFileType());
list.add(list_item);
}
}
setupRecyclerView(list);
fileListRecyclerView.startAnimation(fadeIn);
}
catch (Exception e){
e.printStackTrace();
}
}
private static void setupRecyclerView(ArrayList<FileItem> list){
FileListRecyclerViewAdapter fileListRecyclerViewAdapter = new FileListRecyclerViewAdapter(context,list);
fileListRecyclerView.setAdapter(fileListRecyclerViewAdapter);
fileListRecyclerView.setLayoutManager(new GridLayoutManager(context,3));
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.instantshare">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<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=".UI.Activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".UI.Activities.FilePickerActivity"></activity>
</application>
</manifest>
来源:https://stackoverflow.com/questions/60413633/cant-read-data-from-external-storage-android-emulator