Search code examples
androidtextviewnullpointerexceptionlistactivityfile-browser

TextView NullPointerException using setCompoundDrawablesWithIntrinsicBounds


I was trying to add an icon to the left of each item in a ListView by using the setCompoundDrawablesWithIntrinsicBounds function but keep getting a NullPointerException. I've seen other ways of doing this but was wondering I keep getting this error when trying in this way.

Here is my XML file for each row in the ListView (mediaitems.xml):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mediatext"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="20sp"
>

Here is the code for browsing the directory of an SD card:

public class SDCardExplorer extends ListActivity {

private String mediapath = new String(Environment.getExternalStorageDirectory().getAbsolutePath());

private List<String> item = null;
private List<String> path = null;

private TextView mypath;
private TextView mediatext;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.medialist);

    mypath = (TextView) findViewById(R.id.mypath);
    mediatext = (TextView) findViewById(R.id.mediatext);

    LoadDirectory(mediapath);
}

// class to limit the choices shown when browsing to SD card to media files
public class AudioFilter implements FileFilter {

    // only want to see the following audio file types
    private String[] extension = {".aac", ".mp3", ".wav", ".ogg", ".midi", ".3gp", ".mp4", ".m4a", ".amr", ".flac"};

    @Override
    public boolean accept(File pathname) {

        // if we are looking at a directory that's not hidden we want to see it so return TRUE           
        if (pathname.isDirectory() && !pathname.isHidden()) {
            return true;
        }

        // loops through and determines the extension of all files in the directory
        // returns TRUE to only show the audio files defined in the String[] extension array
        for (String ext : extension) {
            if (pathname.getName().toLowerCase().endsWith(ext)) {
                return true;
            }
        }

        return false;
    }      
}

private void LoadDirectory(String dirPath) {      

    mypath.setText("Location: " + dirPath);

    item = new ArrayList<String>();
    path = new ArrayList<String>();

    File f = new File(dirPath);
    File[] files = f.listFiles(new AudioFilter());

    // If we aren't in the SD card root directory, add "Up" to go back to previous folder
    if(!dirPath.equals(mediapath)) {

        item.add("Up");
        path.add(f.getParent());
        mediatext.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_upicon, 0, 0, 0);
        //mediatext.setCompoundDrawables(getResources().getDrawable(R.drawable.ic_upicon), null, null, null);
    }

    // Loops through the files and lists them
    for (int i = 0; i < files.length; i++) {
        File file = files[i];
        path.add(file.getPath());

        // Add "/" to indicate you are looking at a folder
        if(file.isDirectory()) {
          item.add(file.getName() + "/");
          mediatext.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_foldericon, 0, 0, 0);
        }
        else {
          item.add(file.getName());
          mediatext.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_audioicon, 0, 0, 0);
        }  
    }

    // Displays the directory list on the screen
    setListAdapter(new ArrayAdapter<String>(this, R.layout.mediaitems, item));
}

Here is the LogCat error:

02-03 13:00:48.295: E/ACRA(8231): iSleep fatal error : Unable to start activity ComponentInfo{com.bromancelabs.isleep/com.bromancelabs.isleep.SDCardExplorer}: java.lang.NullPointerException
02-03 13:00:48.295: E/ACRA(8231): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bromancelabs.isleep/com.bromancelabs.isleep.SDCardExplorer}: java.lang.NullPointerException
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
02-03 13:00:48.295: E/ACRA(8231):   at android.os.Handler.dispatchMessage(Handler.java:99)
02-03 13:00:48.295: E/ACRA(8231):   at android.os.Looper.loop(Looper.java:123)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread.main(ActivityThread.java:4627)
02-03 13:00:48.295: E/ACRA(8231):   at java.lang.reflect.Method.invokeNative(Native Method)
02-03 13:00:48.295: E/ACRA(8231):   at java.lang.reflect.Method.invoke(Method.java:521)
02-03 13:00:48.295: E/ACRA(8231):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
02-03 13:00:48.295: E/ACRA(8231):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
02-03 13:00:48.295: E/ACRA(8231):   at dalvik.system.NativeStart.main(Native Method)
02-03 13:00:48.295: E/ACRA(8231): Caused by: java.lang.NullPointerException
02-03 13:00:48.295: E/ACRA(8231):   at com.bromancelabs.isleep.SDCardExplorer.LoadDirectory(SDCardExplorer.java:116)
02-03 13:00:48.295: E/ACRA(8231):   at com.bromancelabs.isleep.SDCardExplorer.onCreate(SDCardExplorer.java:60)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-03 13:00:48.295: E/ACRA(8231):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
02-03 13:00:48.295: E/ACRA(8231):   ... 11 more

Thanks for any help anyone can provide.


Solution

  • I ended up using the below code:

    My rowlayout.xml for each row in the ListView:

        <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    
        <ImageView
            android:id="@+id/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dip"
            android:layout_marginRight="10dip"
            android:layout_marginTop="5dip"
            android:padding="2dip" >
        </ImageView>
    
        <TextView
            android:id="@+id/label"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textSize="25sp" >
        </TextView>
    
    </LinearLayout>
    

    Here's my code for the listview:

        public class SDCardExplorer extends ListActivity {
    
        private String mediapath = new String(Environment.getExternalStorageDirectory().getAbsolutePath());
        private String[] items;
    
        private List<String> item = null;
        private List<String> path = null;
    
        private TextView mypath;
    
        private AlertDialog.Builder alert;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.medialist);
    
            mypath = (TextView) findViewById(R.id.mypath);
    
            LoadDirectory(mediapath);
        }
    
        // class to limit the choices shown when browsing to SD card to media files
        public class AudioFilter implements FileFilter {
    
            // only want to see the following audio file types
            private String[] extension = {".aac", ".mp3", ".wav", ".ogg", ".midi", ".3gp", ".mp4", ".m4a", ".amr", ".flac"};
    
            @Override
            public boolean accept(File pathname) {
    
                // if we are looking at a directory that's not hidden we want to see it so return TRUE           
                if (pathname.isDirectory() && !pathname.isHidden()) {
                    return true;
                }
    
                // loops through and determines the extension of all files in the directory
                // returns TRUE to only show the audio files defined in the String[] extension array
                for (String ext : extension) {
                    if (pathname.getName().toLowerCase().endsWith(ext)) {
                        return true;
                    }
                }
    
                return false;
            }      
        }
    
        // Creates items in the ListView view based on the rowlayout.xml file
        class IconicList extends ArrayAdapter {
    
            public IconicList() {
                super(SDCardExplorer.this, R.layout.rowlayout, items);
            }
    
            public View getView(int position, View convertView, ViewGroup parent) {
    
                View row = convertView;
    
                // If the convertView is null, run the code below to create a new View
                if (row == null) {
                    LayoutInflater inflater = getLayoutInflater();
                    row = inflater.inflate(R.layout.rowlayout, parent, false);
                }
    
                TextView label = (TextView)row.findViewById(R.id.label); 
                ImageView icon = (ImageView)row.findViewById(R.id.icon);
    
                label.setText(items[position]);
    
                String s = items[position];
    
                // Get the file according the position
                File f = new File(path.get(position)); 
    
                // If looking at a directory
                if (f.isDirectory()) { 
                    // If it's the "Home" folder, add the home icon
                    if (s.contains("Home")) {
                        icon.setImageResource(R.drawable.ic_sdrooticon);
                    }
                    // If it's the "Up" folder, add the up icon
                    else if (s.contains("Up")) {
                        icon.setImageResource(R.drawable.ic_upicon);
                    }
                    // Else just add the folder icon
                    else {
                        icon.setImageResource(R.drawable.ic_foldericon);
                    }
                }
                // Else you're looking at an audio icon, so add the audio icon
                else {
                    icon.setImageResource(R.drawable.ic_audioicon);
                }
    
                return(row);
            }   
        }
    
        // Loads directory from SD card represented by the String variable dirPath
        private void LoadDirectory(String dirPath) {      
    
            mypath.setText("Location: " + dirPath);
    
            item = new ArrayList<String>();
            path = new ArrayList<String>();
    
            File f = new File(dirPath);
            File[] files = f.listFiles(new AudioFilter());
    
            // If we aren't in the SD card root directory
            // Add "Home" to go back to the root of the SD card
            // Add "Up" to go back to previous folder
            if(!dirPath.equals(mediapath)) {
    
                item.add("Home");
                path.add(mediapath);
    
                item.add("Up");
                path.add(f.getParent());
            }
    
            // Loops through the files and lists them
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                path.add(file.getPath());
    
                // Add "/" to indicate you are looking at a folder
                if(file.isDirectory()) {
                  item.add(file.getName() + "/");
                }
                else {
                  item.add(file.getName());
                }  
            }
    
            //declare array with specific number off item
            items = new String[item.size()]; 
            //send data arraylist(item) to array(items)
            item.toArray(items); 
            //sets the list with icon
            setListAdapter(new IconicList()); 
        } 
    }