I am using C++ Builder XE8. As the TOpenDialog doesn't work on Android, I am trying to make such thing myself. My logic is very simple. It'll start to check file and folders from "/storage" and show all items on TListView. If I touch a folder (name) it'll open that folder and if I touch a file, it should show the name on a label. So I assigned a function to TListView's OnItemClick event.
Here is code. fpath is String, Label1 is showing current folder and Label2 is showing selected file.
void __fastcall TForm1::lviewitemclck(TObject * const Sender, TListViewItem * const AItem)
{
if (AItem->Text == "<< BACK") {
if (!fpath.LastDelimiter("/") == 0) {
fpath = fpath.SubString(0, fpath.LastDelimiter("/"));
Label1->Text = fpath;
Form1->showfiles(fpath);
}
}
else if ( DirectoryExists(fpath+ AItem->Text)) {
fpath = fpath+ AItem->Text;
Label1->Text = fpath;
Form1->showfiles(fpath);
}
else if (FileExists(fpath+ AItem->Text)) {
Label2->Text ="File: "+ fpath+ AItem->Text;
}
}
Below is the code of function to scan for files & folders and show them. stringlist is TStringList.
void __fastcall TForm1::showfiles (String path)
{
TSearchRec sr; // for scaning files and folders
TSearchRec fr; // to check whether the folder is accessible or not.
if (FindFirst(path+"/*", faAnyFile, sr) == 0)
{
stringlist->Clear();
stringlist->Add("<< BACK"); // being used to replace the ".."
do{
if(sr.Name != "." && sr.Name != ".."){
if (DirectoryExists(path+"/"+sr.Name)) {
if (FindFirst(path+"/"+sr.Name+"/*", faAnyFile, fr) == 0) { // to check if the folder is accessible
stringlist->Add("/"+ sr.Name);
}
FindClose(fr);
}
else{
stringlist->Add("/"+ sr.Name);
}
}
} while (FindNext(sr) == 0);
}
FindClose(sr);
stringlist->Sort();
Form1->Item->Free();
Form1->ListView1->BeginUpdate();
Form1->ListView1->ClearItems();
for( int i =0;i< stringlist->Count; i++){
Form1->Item = Form1->ListView1->Items->Add();
Form1->Item->Text = stringlist->Strings[i];
}
Form1->ListView1->EndUpdate();
}
Here the problem is, if I use ListView1->ClearItems() in TForm1::showfiles it shows me an error saying "Access violation at address (random no), accessing address 00000009". And if I dont use ClearItems() it just add more lines with already existed lines. I am a beginer, so I dont know where I am doing wrong.
You should use:
ListView1->Items->Clear
The best way I have found so far is to dynamically create TListView and delete it each time you want to add new items( or calling showfiles function). I have written a small function (named it refresh) to release already created TListView and call another function(named it create_lview ) which can create an instance again then it calls the showfiles method.
void __fastcall TForm1::refresh()
{
if (!lview1->Released()) {
try{
lview1->Release();
Form1->create_lview();
Form1->showfiles(fpath);
}
catch(...){
Label2->Text = "error in cleaning";
}
}
}
Here is the code to create the TListView whenever you want.
void __fastcall TForm1::create_lview()
{
lview1 = new TListView(Form1);
lview1->Parent = Form1;
lview1->Height = 600;
lview1->Width = 400;
lview1->Position->X = 0;
lview1->Position->Y = 0;
lview1->Visible = true;
lview1->Enabled = true;
lview1->OnItemClick = lviewitemclck;
lview1->CanSwipeDelete = false;
}
Please comment if you find any mistake or you can do it more efficiently.
I have tried another way to avoid the error by replacing the Clear method with updating the Item Text, then deletes the unused last row of the ListView within the ListView1Change event.
void __fastcall TForm1::ListView1Change(TObject *Sender)
{
//Delete last item
while (ListView1->Items->Count>stringlist->Count){
ListView1->Items->Delete(ListView1->Items->Count-1);
}
}
void __fastcall TForm1::showfiles (String path)
{
TSearchRec sr; // for scaning files and folders
TSearchRec fr; // to check whether the folder is accessible or not.
//path+PathDelim+
if (FindFirst(path+PathDelim+'*', faAnyFile, sr) == 0)
{
stringlist->Clear();
stringlist->Add("<<--BACK"); // being used to replace the ".."
do{
if(sr.Name != "." && sr.Name != ".."){
if (DirectoryExists(path+PathDelim+sr.Name)) {
if (FindFirst(path+PathDelim+sr.Name+PathDelim+"*", faAnyFile, fr) == 0) { // to check if the folder is accessible
stringlist->Add(sr.Name);
}
FindClose(fr);
}
else{
stringlist->Add(sr.Name);
}
}
} while (FindNext(sr) == 0);
}
FindClose(sr);
stringlist->Sort();
for( int i =0;i< ListView1->Items->Count; i++){
ListView1->Items->Item[i]->Text="";
}
ListView1->BeginUpdate();
try {
for( int i =0;i< stringlist->Count; i++)
{
if (ListView1->Items->Count-1<i)
{
TListViewItem* Item=ListView1->Items->Add();
Item->Text=stringlist->Strings[i];
} else
{
TListViewItem* Item=ListView1->Items->Item[i];
Item->Text=stringlist->Strings[i];
}
}
}
catch (...) {
}
ListView1->EndUpdate();
/* */
}
Related
This issue is troubling me until 1 week. I want to take picture like bracketing but in Sony Camera API its not support. so I coded it like continuously take 5 pictures with different value (0,+2,-2,-4,+4) using loop. (using button for it, and when press the button it should take picture 5 times) U can see the code in below:
This code for set Shutter Speed on camera
This code for taking picture:
private void takePicture() {
if (mLiveviewSurface == null || !mLiveviewSurface.isStarted()) {
DisplayHelper.toast(getApplicationContext(), R.string.msg_error_take_picture);
return;
}
new Thread() {
#Override
public void run() {
try {
JSONObject replyJson = mRemoteApi.actTakePicture();
JSONArray resultsObj = replyJson.getJSONArray("result");
JSONArray imageUrlsObj = resultsObj.getJSONArray(0);
String postImageUrl = null;
if (1 <= imageUrlsObj.length()) {
postImageUrl = imageUrlsObj.getString(0); continousShottingWithDifferentShutterValue();
}
if (postImageUrl == null) {
Log.w(TAG, "takePicture: post image URL is null.");
DisplayHelper.toast(getApplicationContext(), //
R.string.msg_error_take_picture);
return;
}
// Show progress indicator
DisplayHelper.setProgressIndicator(SonyCameraActivity.this, false);
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
and this is for loop:
int val, posVal = 0;
int currentShutterSpeed = 0;
private void continousShottingWithDifferentShutterValue() {
if (val == 0) {
currentShutterSpeed = -5;
setShutterSpeed(currentShutterSpeed);
val++;
} else if (val == 1) {
currentShutterSpeed = 5;
setShutterSpeed(currentShutterSpeed);
val++;
} else if (val == 2) {
currentShutterSpeed = -10;
setShutterSpeed(currentShutterSpeed);
val++;
} else if (val == 3) {
currentShutterSpeed = 10;
setShutterSpeed(currentShutterSpeed);
val++;
} else if (val == 4) {
setShutterSpeedVal0(0);
posVal++;
}
if (posVal == 3) {
posVal = 0;
val = 0;
}
}
But when I take picture sometimes shutterSpeed or takePicture is getting error and loop is stop.
Error types are: setShutterSpeed IOExeption error: 500; or setShutterSpeed is not set. Someone works with Sonycamera remote API and has any idea how to fix it or take picture 5 times with different value. will thankful for any idea. Thanks
I solved the problem. it was a shutter speed value error. As u know in Sony Camera Api there is not have the value of shutter speed and I wrote it as in camera settings. and JSON request and response is not match so its shows error 500. If someone wants to use shutter speed value: here it is:
String shutterValue[] = {"30\"", "25\"", "20\"", "15\"", "13\"", "10\"", "8\"", "6\"",
"5\"", "4\"", "3.2\"", "2.5\"", "2\"", "1.6\"", "1.3\"", "1\"", "0.8\"", "0.6\"", "0.5\"",
"0.4\"", "1/3", "1/4", "1/5", "1/6", "1/8", "1/10", "1/13", "1/15", "1/20", "1/25", "1/30",
"1/40", "1/50", "1/60", "1/80", "1/100", "1/125", "1/160", "1/200", "1/250", "1/320", "1/400",
"1/500", "1/640", "1/800", "1/1000", "1/1250", "1/1600", "1/2000", "1/2500", "1/3200", "1/4000"};
I'm using ZXing in an Android app being developed in Xamarin to scan a QR code and start playing the corresponding audio file automatically.
My problem is that when I get a result from scanning, it takes some time for the audio player activity to load so it gets called twice or more due to subsequent successful scannings.
Is there a way to stop continuous scanning as soon as I get a correct result?
Here's the code:
//Start scanning
scanner.ScanContinuously(opt, HandleScanResult);
}
private void HandleScanResult(ZXing.Result result)
{
string msg = "";
if (result != null && !string.IsNullOrEmpty(result.Text))
{
msg = result.Text;
var playerActivity = new Intent(myContext, typeof(AudioActivity));
//-------------------------------------------------------------
// Prerequisite: load all tracks onto "Assets/tracks" folder
// You can put here qr code - track assignments here below
// msg: decoded qr code
// playerActivity.Putextra second parameter is a relative path
// under "Assets" directory
//--------------------------------------------------------------
//Iterate through tracks stored in assets and load their titles into an array
System.String[] trackArray = Application.Context.Assets.List("tracks");
bool trackFound = false;
foreach (string track in trackArray)
{
if (track.Equals(msg + ".mp3"))
{
playerActivity.PutExtra("Track", "tracks/" + msg + ".mp3");
for (int i = 0; i < PostList.postList.Count; i++)
{
if (PostList.postList.ElementAt(i).code.Equals(msg))
playerActivity.PutExtra("TrackTitle", PostList.postList.ElementAt(i).title);
}
myContext.StartActivity(playerActivity);
trackFound = true;
}
}
Thank you!
Old question but i'll post it anyway for anyone still looking for this information.
You need your scanner to be a class variable. This is my code:
public MobileBarcodeScanner scanner = new MobileBarcodeScanner();
private void ArrivalsClick(object sender, EventArgs e)
{
try
{
if (Arrivals.IsEnabled)
{
MobileBarcodeScanningOptions optionsCustom = new MobileBarcodeScanningOptions();
scanner.TopText = "Scan Barcode";
optionsCustom.DelayBetweenContinuousScans = 3000;
scanner.ScanContinuously(optionsCustom, ArrivalResult);
}
}
catch (Exception)
{
throw;
}
}
private async void ArrivalResult(ZXing.Result result)
{
if (result != null && result.Text != "")
{
// Making a call to a REST API
if (resp.StatusCode == System.Net.HttpStatusCode.OK)
{
int? res = JsonConvert.DeserializeObject<int>(resp.Content);
if (res == 0)
{
scanner.Cancel(); // <----- Stops scanner (Something went wrong)
Device.BeginInvokeOnMainThread(async () =>
{
await DisplayAlert("..", "..", "ΟΚ");
});
}
else
{
Plugin.SimpleAudioPlayer.ISimpleAudioPlayer player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
player.Load("beep.wav");
player.Play(); // Scan successful
}
}
else
{
scanner.Cancel();
Device.BeginInvokeOnMainThread(async () =>
{
await DisplayAlert("..", "..", "ΟΚ");
});
}
}
}
I need to pick contacts in my app and would like to exclude those which are stored in my SIM card. Is it possible with ACTION_PICK?
No, it's not possible
Unfortunately, it's not possible for now.
To proof it, let's dive into source code of ContanctsListActivity.
Here's an onCreate() method of the Activity. In it, ContactApp reads Intent(ACTION_PICK) we passing to it and handles it respectively:
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mIconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
mContactsPrefs = new ContactsPreferences(this);
mPhotoLoader = new ContactPhotoLoader(this, R.drawable.ic_contact_list_picture);
// Resolve the intent
final Intent intent = getIntent();
// Allow the title to be set to a custom String using an extra on the intent
String title = intent.getStringExtra(UI.TITLE_EXTRA_KEY);
if (title != null) {
setTitle(title);
}
String action = intent.getAction();
String component = intent.getComponent().getClassName();
// When we get a FILTER_CONTACTS_ACTION, it represents search in the context
// of some other action. Let's retrieve the original action to provide proper
// context for the search queries.
if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
mSearchMode = true;
mShowSearchSnippets = true;
Bundle extras = intent.getExtras();
if (extras != null) {
mInitialFilter = extras.getString(UI.FILTER_TEXT_EXTRA_KEY);
String originalAction =
extras.getString(ContactsSearchManager.ORIGINAL_ACTION_EXTRA_KEY);
if (originalAction != null) {
action = originalAction;
}
String originalComponent =
extras.getString(ContactsSearchManager.ORIGINAL_COMPONENT_EXTRA_KEY);
if (originalComponent != null) {
component = originalComponent;
}
} else {
mInitialFilter = null;
}
}
Log.i(TAG, "Called with action: " + action);
mMode = MODE_UNKNOWN;
if (UI.LIST_DEFAULT.equals(action) || UI.FILTER_CONTACTS_ACTION.equals(action)) {
.....
else if (Intent.ACTION_PICK.equals(action)) {
// XXX These should be showing the data from the URI given in
// the Intent.
final String type = intent.resolveType(this);
if (Contacts.CONTENT_TYPE.equals(type)) {
mMode = MODE_PICK_CONTACT;
} else if (People.CONTENT_TYPE.equals(type)) {
mMode = MODE_LEGACY_PICK_PERSON;
} else if (Phone.CONTENT_TYPE.equals(type)) {
mMode = MODE_PICK_PHONE;
} else if (Phones.CONTENT_TYPE.equals(type)) {
mMode = MODE_LEGACY_PICK_PHONE;
} else if (StructuredPostal.CONTENT_TYPE.equals(type)) {
mMode = MODE_PICK_POSTAL;
} else if (ContactMethods.CONTENT_POSTAL_TYPE.equals(type)) {
mMode = MODE_LEGACY_PICK_POSTAL;
}
....
// VERY LONG IF WITH DIFFERENT MODE-SELECTION
....
}
.....
if (mMode == MODE_JOIN_CONTACT) {
setContentView(R.layout.contacts_list_content_join);
} else if (mSearchMode) {
setContentView(R.layout.contacts_search_content);
} else if (mSearchResultsMode) {
setContentView(R.layout.contacts_list_search_results);
} else {
setContentView(R.layout.contacts_list_content);
}
setupListView();
...
}
It's very long method (and I also suggest to check setupListView() method), but pretty straightforward. And, as you can see, there's no parameter you can pass to specify source of contacts you want to pick from. Only thing you can configure here is the particular mMode ContactsApp to use (MODE_PICK_CONTACT, MODE_PICK_PHONE, etc.) - but unfortunately number of possible modes is very limited by 6 and non of them suits you.
(If anyone needs to pass mMode to ContanctsListActivity - use intent's setType() method, for example: intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);)
Workaround
As a workaround - as tiny sunlight's suggested in comments - render non-SIM contacts within the app and pick the one you needed from there.
How to get all android contacts but without those which are on SIM - this link looks like most promising one explaining how to query cursor with all contacts, apart from SIM ones.
I hope, it helps
im using the Google Drive API to save(use as backup) a database there, its working nice, but just if i use the ROOT
the Api Call:
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
......build();
Drive.DriveApi.getRootFolder(mGoogleApiClient)
.createFile(mGoogleApiClient, metadataChangeSet, result.getDriveContents())
.setResultCallback(fileCallback);
CallBack to Save the file:
final public ResultCallback < DriveFolder.DriveFileResult > fileCallback = new
ResultCallback < DriveFolder.DriveFileResult > () {
#Override
public void onResult(DriveFolder.DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
return;
}
Log.i(TAG, "Successfull !");
}
};
i know that i must get the Folder, but if i do this, i need to do a CallBack to call another callback and then save?
isnt any way to directly do .createNewFile inside the FOLDER? without doing another Query for folder, check if the folder exist than create the folder, than use the DriveID, than create the file?
Remember, that in the GooDrive universe, the tree structure (folder, subfolder, ...) is a mirage. The Drive is a flat system of objects (files, folders) where one of the metadata fields is a 'set of parent IDs', that actually forms the notion of parentobject - childobject structure. Actually the classic tree (one parent many children) is not even enforced, so a child object can 'appear' in more that one parent.
This fact explains that you CAN NOT create an OS type of path in one shot. The objects (parents) must be created before their IDs can be plugged into child objects' metadata.
So the only way to do it, is to do what you say:
if folder exists
return it's ID
else
return ID of newly created one
create a child object with parent's ID
... and here is an example how I create a structure of type:
/ MYROOT / 2015 / 2015-12
(where MYROOT, 2015 , 2015-12 are subfloders the Drive root)
new Thread(new Runnable() {
#Override
public void run() {
DriveId Id = getFolder( getFolder( getFolder(
Drive.DriveApi.getRootFolder(mGAC).getDriveId(), "MYROOT"),
"2015",
"2015-12"
);
}
}).start();
GoogleApiClient mGAC;
DriveId getFolder(DriveId parentId, String titl) {
DriveId dId = null;
if (parentId != null && titl != null) try {
ArrayList<Filter> fltrs = new ArrayList<>();
fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
fltrs.add(Filters.eq(SearchableField.TITLE, titl));
fltrs.add(Filters.eq(SearchableField.MIME_TYPE, "application/vnd.google-apps.folder"));
Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();
MetadataBuffer mdb = null;
DriveApi.MetadataBufferResult rslt = Drive.DriveApi.query(mGAC, qry).await();
if (rslt.getStatus().isSuccess()) try {
mdb = rslt.getMetadataBuffer();
if (mdb.getCount() > 0)
dId = mdb.get(0).getDriveId();
} catch (Exception ignore) {}
finally { if (mdb != null) mdb.close(); }
if (dId == null) {
MetadataChangeSet meta = new Builder().setTitle(titl).setMimeType(UT.MIME_FLDR).build();
DriveFolderResult r1 = parentId.asDriveFolder().createFolder(mGAC, meta).await();
DriveFolder dFld = (r1 != null) && r1.getStatus().isSuccess() ? r1.getDriveFolder() : null;
if (dFld != null) {
MetadataResult r2 = dFld.getMetadata(mGAC).await();
if ((r2 != null) && r2.getStatus().isSuccess()) {
dId = r2.getMetadata().getDriveId();
}
}
}
} catch (Exception e) { e.printStackTrace(); }
return dId;
}
In the 'mdb.get(0).getDriveId()' area, you can see how hacky it gets when you try to impose a classic tree structure on the Drive. The search here can return multiple objects with the same name, so I use the first one. There should be some kind of error reporting here.
As you can see it is possible to replace callbacks with the 'await()' method, flattening the code into a classic DOS style spaghetti code as long as you place the whole sequence off-UI thread (asynctask, thread, ....)
Still, more elegant (IMO) option to accomplish this is to use recursive call from the result callback.
fromPath(Drive.DriveApi.getRootFolder(mGAC).getDriveId(), "MYROOT/2015/2015-12/file.jpg");
....
void fromPath(final DriveId parentId, final String path) {
if (parentId != null && path != null) {
final int idx = path.indexOf('/');
if (idx < 0) {
// reached last path item - probably file name
// CREATE FILE WITH patentID AND QUIT
return; //--- DONE -------------------->>>
}
final String titl = path.substring(0, idx);
ArrayList<Filter> fltrs = new ArrayList<>();
fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
fltrs.add(Filters.eq(SearchableField.TITLE, titl));
fltrs.add(Filters.eq(SearchableField.MIME_TYPE, UT.MIME_FLDR));
Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();
Drive.DriveApi.query(mGAC, qry).setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
#Override
public void onResult(DriveApi.MetadataBufferResult rslt) {
MetadataBuffer mdb = null;
if (rslt != null && rslt.getStatus().isSuccess()) {
try {
mdb = rslt.getMetadataBuffer();
for (Metadata md : mdb) {
if (md.isTrashed()) continue;
fromPath(md.getDriveId(), path.substring(idx + 1));
return; //+++ first found, NEXT +++++++>>>
}
} finally { if (mdb != null) mdb.close(); }
}
MetadataChangeSet meta = new Builder().setTitle(titl).setMimeType(UT.MIME_FLDR).build();
parentId.asDriveFolder().createFolder(mGAC, meta)
.setResultCallback(new ResultCallback<DriveFolderResult>() {
#Override
public void onResult(DriveFolderResult rslt) {
DriveFolder dFld = rslt != null && rslt.getStatus().isSuccess() ? rslt.getDriveFolder() : null;
if (dFld != null) {
dFld.getMetadata(mGAC).setResultCallback(new ResultCallback<MetadataResult>() {
#Override
public void onResult(MetadataResult rslt) {
if (rslt != null && rslt.getStatus().isSuccess()) {
fromPath(rslt.getMetadata().getDriveId(), path.substring(idx + 1));
return; //+++ created, NEXT +++++++>>>
}
}
});
}
}
});
}
});
}
}
A WORD OF CAUTION:
As I called this sequence repeatedly, using the last DriveId (like 2015-12) as a parent of a JPEG image file, I have experienced weird behavior, like suddenly getting a 'null' result from 'Drive.DriveApi.getRootFolder(mGAC).getDriveId()'. It shouldn't happen and I assume it is a bug in GDAA. I contribute this to the fact that the DriveId used inside GDAA is 'invalid' until the folder gets committed and the ResourceId is resolved in underlying REST Api. Unfortunately, there is no completion event available for folder creation, so I resolved this by calling this sequence only once in onConnected() and caching the '2015-12's DriveId for later use as a parent of the image JPEG files.
Actually you can see it here (createTree() method) with text file on the tail, but the moment I switched the TEXT to JPEG, all hell broke lose.
Good Luck
My Android application needs to look into the default Camera directory and get the names of JPEG files created within a time range. I currently do this with the below code snippet.
The idea is to filter out files not only by the "jpg" extension but also to use the fact that the file names have date/time in them.
I run the below getImages() function within a Thread so the UI itself isn't affected.
I notice that it takes a while if there are lot of files in the directory even after all this. Is there a faster algorithm or Android specific functions that I can use to optimize it further?
private boolean getImages()
{
boolean status=true;
File dir = new File(picPath);
//Optimize file search by setting the common file prefix as a filter
//get the date format used by camera to store files.
String startStr=startTime.format3339(false);
String endStr=endTime.format3339(false);
//Loop through each character of start time
//and compare with end time till a mismatch is found
int len=startStr.length();
int idx=0;
for ( idx=0;id < len;idx++ )
{
if (startStr.charAt(idx) != endStr.charAt(idx))
{
Log.d(TAG,"breaking at idx "+ idx);
break;
}
}
filterString=endStr.substring(0,idx).replace("T", " ").replace(":",".");
Log.d(TAG,"Filter String" + filterString);
String[] children = dir.list(new JpegFilter());
List matchedFiles = new ArrayList();
Log.d(TAG,dir.getAbsolutePath()+" has "+ children.length+ " files");
int numfiles = children.length;
for(int i=0;i < numfiles;i++)
{
//Get file modify time
File file = new File(picPath+File.separator+children[i]);
// Get the last modification information.
long lastModified = file.lastModified();
if (lastModified > =startTime.toMillis(false)) //If file modified date greater than equals start time
{
Log.d(TAG,"Match! " + children[i]);
if (lastModified < =endTime.toMillis(false))//If file modified date less than equals end time
{
matchedFiles.add(picPath+File.separator+children[i]);
}
else //We are now over the time range, quit loop to save time
{
break; //TODO break out of for loop
}
}
}
if (!matchedFiles.isEmpty()) //If there are images to be processed
{
status=convertToPDF(matchedFiles,pdfFile);
Log.d(TAG,"convertToPDF() returned " + status);
}
return status;
}
This is the Filter class I use
class JpegFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return (name.startsWith(captureJPEG.filterString) && name.endsWith(".jpg"));
}
}
See http://androidworkz.com/2010/07/08/source-code-find-files-by-type-play-media-file/
public class FileUtils {
public File[] listFilesAsArray(File directory, FilenameFilter[] filter,
int recurse) {
Collection<File> files = listFiles(directory, filter, recurse);
File[] arr = new File[files.size()];
return files.toArray(arr);
}
public Collection<File> listFiles(File directory,
FilenameFilter[] filter, int recurse) {
Vector<File> files = new Vector<File>();
File[] entries = directory.listFiles();
if (entries != null) {
for (File entry : entries) {
for (FilenameFilter filefilter : filter) {
if (filter == null
|| filefilter
.accept(directory, entry.getName())) {
files.add(entry);
Log.v("FileUtils", "Added: "
+ entry.getName());
}
}
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
recurse--;
files.addAll(listFiles(entry, filter, recurse));
recurse++;
}
}
}
return files;
}
}
Have you taken a look at the Android File Browser example written here? Maybe you can use this example and tweak it for your specific needs. Im not sure if this is faster, but its a good starting point to consider an alternative approach to your objective.