I am new to android development here and I want to open internal memory from my app. But it is open on all devices except Samsung device. It's showing fine on Motorola device, other phones and in Emulator also. I am getting null here: if (scanFolder == null) {return null;}
public List<Folder> loadInBackground() {
List<Folder> folderList = new ArrayList<>();
List<Song> songList = new ArrayList<>();
// Permission Check Runtime For M and above
if (PermissionChecker.checkCallingOrSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PermissionChecker.PERMISSION_GRANTED) {
FileExtensionFilter mFileExtensionFilter = new FileExtensionFilter(Constants.fileExtensions);
if (dir != null) {
File[] scanFolder = dir.listFiles(mFileExtensionFilter);
// Getting Null over here in Samsung Device scanFolder getting null
if (scanFolder == null) {
return null;
}
// Get Folder List
for (File aScanFolder : scanFolder) {
Folder folder = new Folder();
Cursor cursor = getContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media.DATA}, MediaStore.Audio.Media.DATA + " like ? ", new String[]{"%" + aScanFolder.getAbsolutePath() + "%"}, null);
if (cursor != null) {
int count = cursor.getCount();
if (count != 0) {
if (!aScanFolder.isDirectory()) {
String path = aScanFolder.getAbsolutePath();
Song song = Helper.getSongData(Extras.getInstance().getSongSortOrder(), getContext(), path);
songList.add(song);
}
if (!aScanFolder.getAbsolutePath().startsWith("/d")) {
Log.e("FolderLoader", "Path --> " + aScanFolder.getAbsolutePath());
folder.setFile(aScanFolder);
folder.setFileCount(count);
folder.setSongList(songList);
folderList.add(folder);
}
}
}
if (cursor != null) {
cursor.close();
}
}
Collections.sort(folderList, new Comparator<Folder>() {
#Override
public int compare(Folder f1, Folder f2) {
if ((f1.getFile().isDirectory() && f2.getFile().isDirectory()))
return f1.getFile().getName().compareToIgnoreCase(f2.getFile().getName());
else if (f1.getFile().isDirectory() && !f2.getFile().isDirectory())
return -1;
else if (!f1.getFile().isDirectory() && f2.getFile().isDirectory())
return 1;
else if (!f1.getFile().isDirectory() && !f2.getFile().isDirectory())
return f1.getFile().getName().compareToIgnoreCase(f2.getFile().getName());
else return 0;
}
});
if (!dir.getAbsolutePath().equals("/")) {
Folder folder = new Folder();
if (dir.getParentFile() != null) {
folder.setFile(dir.getParentFile());
Log.e("FolderLoader", dir.getParentFile().getAbsolutePath());
folderList.add(0, folder);
}
}
}
return folderList;
} else {
// Error Message
Log.d("Folder", "Permission not granted");
return Collections.emptyList();
}
}
I am getting this Screen UI in Samsung Device.
Getting All songs in Other device except Samsung Device
Related
I am trying to understand how Android internal storage works.
For that I read a few tutorials and a number of posts on StackOverFlow.
Nevertheless things are not all that clear when testing real code.
Here is one problem, the following code is meant to create a directory and a file:
val dirName = "myNewDir"
createDir(dirName)
val fileName = "myNewFile"
writeToFile("Some random text for testing purpose ...",fileName)
val directory = filesDir
val files: Array<File> = directory.listFiles()
println("Files count = "+files.size)
for (f in files) {
println("Name: "+f.name)
}
This is the code for the two functions createDir() and writeToFile() :
fun createDir(dirName:String): File? {
return applicationContext.getDir(dirName, MODE_PRIVATE)
} /* End of createDir */
fun writeToFile(dataBufr:String, fileName:String) {
applicationContext.openFileOutput(fileName, Context.MODE_PRIVATE).use {
output -> output.write(dataBufr.toByteArray())
}
} /* End of writeToFile */
And this is what appears in the console when executing the code above:
I/System.out: Files count = 1
I/System.out: Name: myNewFile
My question is:
Why is the directory (myNewDir) not created or at list does not appear in the console?
Latest android version, all default dirs will be created in the first open by LoadAPK.java, getDir will get the exists dir.
public File getDir(String name, int mode) {
checkMode(mode);
name = "app_" + name;
File file = makeFilename(getDataDir(), name);
if (!file.exists()) {
file.mkdir();
setFilePermissionsFromMode(file.getPath(), mode,
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
}
return file;
}
In the getDataDir()
#Override
public File getDataDir() {
if (mPackageInfo != null) {
File res = null;
if (isCredentialProtectedStorage()) {
res = mPackageInfo.getCredentialProtectedDataDirFile();
} else if (isDeviceProtectedStorage()) {
res = mPackageInfo.getDeviceProtectedDataDirFile();
} else {
res = mPackageInfo.getDataDirFile();
}
if (res != null) {
if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
Log.wtf(TAG, "Data directory doesn't exist for package " + getPackageName(),
new Throwable());
}
return res;
} else {
throw new RuntimeException(
"No data directory found for package " + getPackageName());
}
} else {
throw new RuntimeException(
"No package details found for package " + getPackageName());
}
}
In the frameworks/base/core/java/android/app/LoadedApk.java all file will be init by ApplicationInfo.
private void setApplicationInfo(ApplicationInfo aInfo) {
final int myUid = Process.myUid();
aInfo = adjustNativeLibraryPaths(aInfo);
mApplicationInfo = aInfo;
mAppDir = aInfo.sourceDir;
mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
mLegacyOverlayDirs = aInfo.resourceDirs;
mOverlayPaths = aInfo.overlayPaths;
mDataDir = aInfo.dataDir;
mLibDir = aInfo.nativeLibraryDir;
mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
mDeviceProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceProtectedDataDir);
mCredentialProtectedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialProtectedDataDir);
mSplitNames = aInfo.splitNames;
mSplitAppDirs = aInfo.splitSourceDirs;
mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
mSplitClassLoaderNames = aInfo.splitClassLoaderNames;
if (aInfo.requestsIsolatedSplitLoading() && !ArrayUtils.isEmpty(mSplitNames)) {
mSplitLoader = new SplitDependencyLoaderImpl(aInfo.splitDependencies);
}
}
frameworks/base/core/java/android/os/FileUtils.java
public static #Nullable File newFileOrNull(#Nullable String path) {
return (path != null) ? new File(path) : null;
}
public static #Nullable File createDir(File baseDir, String name) {
final File dir = new File(baseDir, name);
return createDir(dir) ? dir : null;
}
public static boolean createDir(File dir) {
if (dir.mkdir()) {
return true;
}
if (dir.exists()) {
return dir.isDirectory();
}
return false;
}
I am using ActivityResultContracts.OpenDocumentTree() to allow the user to select the folder where they copied several folders which have a list of image files (the image files may be several folders deep from the folder they selected). I need to search for a known folder name and retrieve the image files. I'm trying to do it so that the user does not have to select each of the image files. I can use other data to search and find the correct folder(s) and image files once the "root" folder is know. The problem I am having is trying to convert the Uri returned from the ActivityResult into a File (directory) to search for the sub-folder. The resulting "File" is not a valid File. Maybe this is not the correct way to do this? I would like to support Build.VERSION_CODES.Q and earlier versions of Android. Is this the wrong approach?
Here is what I have tried. In this sample, I'm not doing anything yet with the files since I'm not getting them.
Fragment
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
mViewModel = new ViewModelProvider(this).get(ImportImagesViewModel.class);
Uri uri = Uri.parse("");
selectImageFolder.launch(uri);
}
ActivityResultLauncher<Uri> selectImageFolder = registerForActivityResult(
new ActivityResultContracts.OpenDocumentTree(), new ActivityResultCallback<Uri>()
{
#Override
public void onActivityResult(Uri result)
{
try {
if (result != null) {
for (MetalItem metalItem : MetalsGlobal.GetMetalItems()) {
getImageFilesFromImageFolder(new File(result.getPath()), metalItem.Source, metalItem.OrderNumber, String.valueOf(metalItem.OrderItemNumber));
}
} else {
Toast.makeText(requireContext(), "Nothing selected...", Toast.LENGTH_LONG).show();
}
} catch (Exception x) {
Log.e("Import Inventory Get File Launcher", x.getMessage(), x);
Toast.makeText(requireContext(), x.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
private void getImageFilesFromImageFolder(File folder, #NonNull String source, #NonNull String orderNumber, #NonNull String itemNumber)
{
if (folder == null ||
source.length() == 0 ||
orderNumber.length() == 0 ||
itemNumber.length() == 0)
return;
File[] sourceFolders = folder.listFiles();
if (sourceFolders == null) return;
for (File sourceFolder : sourceFolders) {
if (!sourceFolder.isDirectory())
continue;
if (!sourceFolder.toString().equalsIgnoreCase(source))
continue;
File[] orderNumberFolders = sourceFolder.listFiles();
if (orderNumberFolders == null) return;
for (File orderNumberFolder : orderNumberFolders) {
if (!orderNumberFolder.isDirectory())
continue;
if (!orderNumberFolder.toString().equalsIgnoreCase(orderNumber))
continue;
File[] itemNumberFolders = orderNumberFolder.listFiles();
if (itemNumberFolders == null) return;
for (File itemNumberFolder : itemNumberFolders) {
if (!itemNumberFolder.isDirectory())
continue;
if (!itemNumberFolder.toString().equalsIgnoreCase(itemNumber))
continue;
// Here should be the image files
File[] imageFiles = itemNumberFolder.listFiles();
if (imageFiles == null) return;
for (File imageFile : imageFiles) {
if (!(imageFile.isFile() && imageFile.canRead()))
return;
try {
Uri imageUri = Uri.parse(imageFile.toString());
int blah = imageUri.toString().length();
} catch (Exception x) {
return;
}
}
}
}
}
}
Based on the suggestion from CommonsWare this is the revised method which works exactly like I need.
private void processImageFolder(DocumentFile folder, MetalItem metalItem)
{
String source = metalItem.Source;
String orderNumber = metalItem.OrderNumber;
String itemNumber = String.valueOf(metalItem.OrderItemNumber);
if (folder == null ||
source.length() == 0 ||
orderNumber.length() == 0 ||
itemNumber.length() == 0)
return;
DocumentFile[] sourceFolders = folder.listFiles();
for (DocumentFile sourceFolder : sourceFolders) {
if (!sourceFolder.isDirectory())
continue;
if (!Objects.requireNonNull(sourceFolder.getName()).equalsIgnoreCase(source))
continue;
DocumentFile[] orderNumberFolders = sourceFolder.listFiles();
for (DocumentFile orderNumberFolder : orderNumberFolders) {
if (!orderNumberFolder.isDirectory())
continue;
if (!Objects.requireNonNull(orderNumberFolder.getName()).equalsIgnoreCase(orderNumber))
continue;
DocumentFile[] itemNumberFolders = orderNumberFolder.listFiles();
for (DocumentFile itemNumberFolder : itemNumberFolders) {
if (!itemNumberFolder.isDirectory())
continue;
if (!Objects.requireNonNull(itemNumberFolder.getName()).equalsIgnoreCase(itemNumber))
continue;
// Here should be the image files
DocumentFile[] imageFiles = itemNumberFolder.listFiles();
for (DocumentFile imageFile : imageFiles) {
if (!(imageFile.isFile() && imageFile.canRead()))
return;
try {
loadItemImage(metalItem, imageFile);
} catch (Exception x) {
return;
}
}
return;
}
}
}
}
I am really stuck as I have a cursor that retrieves values from the database but the cursor only returns the last value. I need the cursor to retrieve all values so I can display them all later on. Is there any way as I can return all the data stored through the cursor?
An Example as to whats happening. Eg Click on Button 1 and stores 1 perfectly but once I click on Button 2 and add 1. Button 1 data is not return or retrieved.
Any help would be greatly appreciated.
Execute
The first Cursor is goes through to check all the stored items.
public void exectute() {
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Cursor c = TrackerDb.getStoredItems(getApplicationContext());
if (c != null) {
if (c.moveToFirst()) {
WorkoutDetails details = null;
//if (details != null) mWorkoutDetailsList.add(details);
do {
//if (details != null) mWorkoutDetailsList.add(details);
WorkoutDetails temp = getWorkoutFromCursor(c);
//if (details != null) mWorkoutDetailsList.add(details);
if (details == null) {
details = temp;
continue;
}
//if (details != null) mWorkoutDetailsList.add(details);
if (isSameDay(details.getWorkoutDate(), temp.getWorkoutDate())) {
//if (details != null) mWorkoutDetailsList.add(details);
if (DBG) Log.d(LOG_TAG, "isSameDay().. true");
//details.add(temp);
} else {
mWorkoutDetailsList.add(details);
details = temp;
}
// if (details != null) mWorkoutDetailsList.add(details);
} while (c.moveToNext());
if (details != null) mWorkoutDetailsList.add(details);
if (DBG)
Log.d(LOG_TAG, "AsyncTask: list size " + mWorkoutDetailsList.size());
runOnUiThread(new Runnable() {
#Override
public void run() {
mWorkoutsAdapter.updateList(mWorkoutDetailsList);
}
});
}
c.close();
}
}
});
}
Get Stored Items Code
This is the code which the excute class calls and where the cursor only returns one value.
public static Cursor getStoredItems(Context context) {
DBHelper dbHelper = new DBHelper(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();
String[] projection = {ID, TIME, TYPE, DURATION, DATE, POINT};
String orderBy = TIME + " DESC";
Cursor cursor = db.query(TABLE_NAME, projection, null, null, null, null, orderBy);
return cursor;
}
Array
This is the array code where i want the cursor to store its values based on type.
private WorkoutDetails getWorkoutFromCursor(Cursor c) {
long time = c.getLong(c.getColumnIndex(TrackerDb.TIME));
int type = c.getInt(c.getColumnIndex(TrackerDb.TYPE));
int duration = c.getInt(c.getColumnIndex(TrackerDb.DURATION));
int point = c.getInt(c.getColumnIndex(TrackerDb.POINT));
int totalMoney = MoneyActivity.Money.values().length;
int[] points = new int[totalMoney];
int totalActivities = MeditationTrackerActivity.ACTIVITIES.values().length;
int[] durations = new int[totalActivities];
if (type < totalActivities) {
durations[type] = duration;
}
if( type == 0) {
for (int i = 0; i < totalMoney; i++) {
points[type] = point;
}
}
else if ( type == 1) {
for ( int ii = 0; ii < totalMoney; ii++) {
points[type] = point;
}
}
else if ( type == 2) {
for ( int iii = 0; iii < totalMoney; iii++) {
points[type] = point;
}
}
return new WorkoutDetails(time, durations, points);
}
Get Workout From Cursor Code
private static WorkoutDetails getWorkoutFromCursor(Cursor c) {
long time = c.getLong(c.getColumnIndex(TrackerDb.TIME));
int type = c.getInt(c.getColumnIndex(TrackerDb.TYPE));
int duration = c.getInt(c.getColumnIndex(TrackerDb.DURATION));
String date = c.getString(c.getColumnIndex(TrackerDb.DATE));
int point = c.getInt(c.getColumnIndex(TrackerDb.POINT));
int[] durations = new int[MeditationTrackerActivity.ACTIVITIES.values().length];
durations[type] = duration;
int[] points = new int[MoneyActivity.Money.values().length];
points[type] = point;
return new WorkoutDetails(time, durations, date, points);
}
Though i got so many post but problem is that
it return true if phone has inbuild storage.
Anyone for help me
Below code will helps...
/**
* Returns all available external SD-Card roots in the system.
*
* #return paths to all available external SD-Card roots in the system.
*/
public static String[] getStorageDirectories() {
String[] storageDirectories;
String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
List<String> results = new ArrayList<String>();
File[] externalDirs = myContext.getExternalFilesDirs(null);
for (File file : externalDirs) {
String path = null;
try {
path = file.getPath().split("/Android")[0];
} catch (Exception e) {
e.printStackTrace();
path = null;
}
if (path != null) {
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file))
|| rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)) {
results.add(path);
}
}
}
storageDirectories = results.toArray(new String[0]);
} else {
final Set<String> rv = new HashSet<String>();
if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
storageDirectories = rv.toArray(new String[rv.size()]);
}
return storageDirectories;
}
//To check external SD is available or not
String retArray[] = getStorageDirectories();
if (retArray.length == 0) {
Toast.makeText(ListenActivity.this, "Sdcard not Exists", Toast.LENGTH_SHORT).show();
} else {
for (int i = 0; i < retArray.length; i++) {
Log.e("path ", retArray[i]);
}
}
I'm in the process of adding Actionbarsherlock to my app to update the UI for Android 2.2/2.3 users. ABS is working great but I found an issue with older devices where the ListView would hang after the app was opened after a reboot. The app lists all apps with Internet Permission and then adds a few special apps (the app is a firewall) and would hang while trying to display the information.
Originally the code cached the apps after building the list using standard arrays. I want to move the app away from the caching since i think that's a huge reason for some of the hanging. So I've been moving everything from arrays to ArrayLists for easier usage. I ran into one IndexOutofBounds but corrected that one but this one is stumping me completely. Here is my code for getting the apps and sorting code.
Any help would be greatly appreciated and if any other code is needed please ask!
Thanks in advance!
App list code:
int count = 0;
try {
final PackageManager pkgmanager = ctx.getPackageManager();
final List<ApplicationInfo> installed = pkgmanager
.getInstalledApplications(PackageManager.GET_META_DATA);
final HashMap<Integer, DroidApp> map = new HashMap<Integer, DroidApp>();
final Editor edit = prefs.edit();
boolean changed = false;
String name = null;
String cachekey = null;
final String cacheLabel = "cache.label.";
DroidApp app = null;
for (final ApplicationInfo apinfo : installed) {
count = count + 1;
if(applist != null){
applist.doProgress(count);
}
boolean firstseen = false;
app = map.get(apinfo.uid);
// filter applications which are not allowed to access the
// Internet
if (app == null
&& PackageManager.PERMISSION_GRANTED != pkgmanager
.checkPermission(Manifest.permission.INTERNET,
apinfo.packageName)) {
continue;
}
// try to get the application label from our cache -
// getApplicationLabel() is horribly slow!!!!
cachekey = cacheLabel + apinfo.packageName;
name = prefs.getString(cachekey, "");
if (name.length() == 0) {
// get label and put on cache
name = pkgmanager.getApplicationLabel(apinfo).toString();
edit.putString(cachekey, name);
changed = true;
firstseen = true;
}
if (app == null) {
app = new DroidApp();
app.uid = apinfo.uid;
app.names = new ArrayList<String>();
app.names.add(name);
app.appinfo = apinfo;
map.put(apinfo.uid, app);
} else {
app.names.add(name);
}
app.firstseen = firstseen;
// check if this application is selected
if (!app.selected_wifi
&& Arrays.binarySearch(selected_wifi, app.uid) >= 0) {
app.selected_wifi = true;
}
if (!app.selected_3g
&& Arrays.binarySearch(selected_3g, app.uid) >= 0) {
app.selected_3g = true;
}
if (!app.selected_roaming
&& Arrays.binarySearch(selected_roaming, app.uid) >= 0) {
app.selected_roaming = true;
}
if (!app.selected_vpn
&& Arrays.binarySearch(selected_vpn, app.uid) >= 0) {
app.selected_vpn = true;
}
}
if (changed) {
edit.commit();
}
/* add special applications to the list */
List<DroidApp> special = new ArrayList<DroidApp>();
special.add(new DroidApp(
SPECIAL_UID_ANY,
"(Any application) - Same as selecting all applications", false, false, false, false));
special.add(new DroidApp(SPECIAL_UID_KERNEL, "(Kernel) - Linux kernel", false, false, false, false));
special.add(new DroidApp(android.os.Process.getUidForName("root"), "(root) - Applications running as root", false, false, false, false));
special.add(new DroidApp(android.os.Process.getUidForName("media"),"Media server", false, false, false, false));
special.add(new DroidApp(android.os.Process.getUidForName("vpn"), "VPN networking", false, false, false, false));
special.add(new DroidApp(android.os.Process.getUidForName("shell"), "Linux shell", false, false, false, false));
special.add(new DroidApp(android.os.Process.getUidForName("gps"), "GPS", false, false, false, false));
for (int i = 0; i < special.size(); i++) {
app = special.get(i);
if (app.uid != -1 && !map.containsKey(app.uid)) {
// check if this application is allowed
if (Arrays.binarySearch(selected_wifi, app.uid) >= 0) {
app.selected_wifi = true;
}
if (Arrays.binarySearch(selected_3g, app.uid) >= 0) {
app.selected_3g = true;
}
if (Arrays.binarySearch(selected_roaming, app.uid) >= 0) {
app.selected_roaming = true;
}
if (Arrays.binarySearch(selected_vpn, app.uid) >= 0) {
app.selected_vpn = true;
}
map.put(app.uid, app);
}
}
/* convert the map into an array */
applications = new ArrayList<DroidApp>(map.values());
return applications;
Sorting code:
class ApplicationSort implements Comparator<DroidApp> {
#Override
public int compare(DroidApp o1, DroidApp o2) {
if (o1.firstseen != o2.firstseen) {
return (o1.firstseen ? -1 : 1);
}
boolean o1_selected;
boolean o2_selected;
boolean vpnenabled = getApplicationContext()
.getSharedPreferences(Api.PREFS_NAME, 0).getBoolean(
Api.PREF_VPNENABLED, false);
boolean roamenabled = getApplicationContext()
.getSharedPreferences(Api.PREFS_NAME, 0).getBoolean(
Api.PREF_ROAMENABLED, false);
if (vpnenabled && !roamenabled) {
o1_selected = o1.selected_3g || o1.selected_wifi
|| o1.selected_vpn;
o2_selected = o2.selected_3g || o2.selected_wifi
|| o2.selected_vpn;
if (o1_selected == o2_selected) {
return String.CASE_INSENSITIVE_ORDER.compare(
o1.names.get(0).toString(), o2.names.get(0).toString());
}
if (o1_selected)
return -1;
}
if (roamenabled && !vpnenabled) {
o1_selected = o1.selected_3g || o1.selected_wifi
|| o1.selected_roaming;
o2_selected = o2.selected_3g || o2.selected_wifi
|| o2.selected_roaming;
if (o1_selected == o2_selected) {
return String.CASE_INSENSITIVE_ORDER.compare(
o1.names.get(0).toString(), o2.names.get(0).toString());
}
if (o1_selected)
return -1;
}
if (roamenabled && vpnenabled) {
o1_selected = o1.selected_3g || o1.selected_wifi
|| o1.selected_roaming || o1.selected_vpn;
o2_selected = o2.selected_3g || o2.selected_wifi
|| o2.selected_roaming || o2.selected_vpn;
if (o1_selected == o2_selected) {
return String.CASE_INSENSITIVE_ORDER.compare(
o1.names.get(0).toString(), o2.names.get(0).toString());
}
if (o1_selected)
return -1;
}
if (!roamenabled && !vpnenabled) {
o1_selected = o1.selected_3g || o1.selected_wifi;
o2_selected = o2.selected_3g || o2.selected_wifi;
if (o1_selected == o2_selected) {
return String.CASE_INSENSITIVE_ORDER.compare(
o1.names.get(0).toString(), o2.names.get(0).toString());
}
if (o1_selected)
return -1;
}
return 1;
}
}
ListView code that calls the sorting class
private void createListView(final String searching) {
this.dirty = false;
boolean results = false;
List<DroidApp> namesearch = new ArrayList<DroidApp>();
final List<DroidApp> appnames = Api.getApps(this, null);
if (searching != null && searching.length() > 1) {
for (DroidApp app : appnames) {
for (String str : app.names) {
if (str.contains(searching.toLowerCase())
|| str.toLowerCase().contains(
searching.toLowerCase())) {
namesearch.add(app);
results = true;
}
}
}
}
final List<DroidApp> apps = results ? namesearch
: searching.equals("") ? appnames
: new ArrayList<Api.DroidApp>();
// Sort applications - selected first, then alphabetically
Collections.sort(apps, new ApplicationSort());
I do not see what is DroidApp, but you are using something like this:
o1.names.get(0) and o2.names.get(0)
Is it possible that some of the DroidApps have empty names lists?