I am trying to export the SQLite db of the app to CSV file and store in SD card. The exporting method was defined in DBAdapter class as ExportToCSV. I have check that the app create a SQLite database successfully. However, when I try to call ExportToCSV using onPause method in MainActivity, the app can not response to export the database. Can you give me any comments on how to correct this code? I will appreciate your help!
My code is as follows:
public void ExportToCSV(Cursor c, String fileName) {
int rowCount = 0;
int colCount = 0;
FileWriter fw;
BufferedWriter bfw;
File sdCardDir = Environment.getExternalStorageDirectory();
File saveFile = new File(sdCardDir, fileName);
try {
rowCount = c.getCount();
colCount = c.getColumnCount();
fw = new FileWriter(saveFile);
bfw = new BufferedWriter(fw);
if (rowCount > 0) {
c.moveToFirst();
// write the colume title
for (int i = 0; i < colCount; i++) {
if (i != colCount - 1)
bfw.write(c.getColumnName(i) + ',');
else
bfw.write(c.getColumnName(i));
}
// change the line
bfw.newLine();
// write data
for (int i = 0; i < rowCount; i++) {
c.moveToPosition(i);
Log.v("exporting data", "exportting" + (i + 1) + "line");
for (int j = 0; j < colCount; j++) {
if (j != colCount - 1)
bfw.write(c.getString(j) + ',');
else
bfw.write(c.getString(j));
}
// change line
bfw.newLine();
}
}
I use onPause in MainActivity.java to call ExportToCSV:
#Override
protected void onPause() {
super.onPause();
DBAdapter myDatabase=new DBAdapter(this);
myDatabase.open();
Cursor c=myDatabase.getAllgpspoint();
// this method was defined in DBAdapter.java and returned a Cursor
myDatabase.ExportToCSV(c, "IRI.csv");
myDatabase.close();
mSensorManager.unregisterListener(this);
}
You must close the file at the end.
bfw.close();
Related
I want to ask export data to text file with spaces(PadRight) like this
Date (max 10 characters) and Barcode (max 14 characters) and Qty 1 (max 8 characters) and Qty 2 (max 8 characters)
Date Barcode Q1 Q2
--------------------------------------
21/03/2022,123456 ,10 ,4
21/03/2022,0909 ,3 ,9
now i don't use spaces(pad) like this
Date Barcode Q1 Q2
21/03/2022,123456,10,4
21/03/2022,0909,3,9
This is my code
btn_export.setOnClickListener(new View.OnClickListener() {
SQLiteDatabase db = controller.getReadableDatabase();
Cursor c = null;
#Override
public void onClick(View v) { //main code begins here
try {
c = db.rawQuery("select TanggalScan,KodeBarcode,QtyGudang,QtyToko from tblscandata", null);
int rowcount = 0;
int colcount = 0;
File sdCardDir = Environment.getExternalStorageDirectory();
String filename = "OPANAME.txt";
File saveFile = new File(sdCardDir,filename);
FileWriter fw = new FileWriter(saveFile);
Log.e("File path", filename);
BufferedWriter bw = new BufferedWriter(fw);
rowcount = c.getCount();
colcount = c.getColumnCount();
if (rowcount > 0) {
c.moveToFirst();
for (int i = 0; i < rowcount; i++) {
c.moveToPosition(i);
for (int j = 0; j < colcount; j++) {
if (j != colcount - 1)
bw.write(c.getString(j) + ",");
else
bw.write(c.getString(j));
}
bw.newLine();
}
bw.flush();
lbl.setText("Exported Successfully.");
controller = new DBController(getApplicationContext());
SQLiteDatabase db = controller.getWritableDatabase();
db.execSQL("delete from " + DBController.TableScan);
}
} catch (Exception ex) {
if (db.isOpen()) {
db.close();
lbl.setText(ex.getMessage().toString());
}
} finally {
}
}
});
this my code
I am able to fetch all the images from any specified non hidden folder from device but how can I get all the images from a hidden specified folder.
As soon as I mention my hidden folder name in the query, cursor return null
public static List<MediaData> getAppScannedImages(Context context) {
Cursor imagecursor = null;
List<MediaData> gallerydata = new ArrayList<MediaData>();
try {
final String orderBy = Images.ImageColumns.DATE_TAKEN + " DESC";
imagecursor = context.getContentResolver()
.query(Images.Media.EXTERNAL_CONTENT_URI,
projectionImage,
Images.Media.BUCKET_DISPLAY_NAME + "='"
+ ".myHiddenFolder" + "'", null,
orderBy);
if (imagecursor != null) {
imagecursor.moveToFirst();
int count = imagecursor.getCount();
for (int i = 0; i < count; i++) {
MediaData galData = new MediaData();
galData.setKey_id(i);
galData.setId(imagecursor.getString(0));
galData.setName(imagecursor.getString(1));
galData.setPath(imagecursor.getString(2));
galData.setDate(imagecursor.getString(3));
gallerydata.add(galData);
imagecursor.moveToNext();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (imagecursor != null) {
imagecursor.close();
}
}
return gallerydata;
}
You can try a different approach.
You have to find out the list of hidden folder from sd card and search all those folders for images.
the follwoing code is displays hidden files:
public void goTODir(File dir) {
//dir is initail dir like="/mnt/sdcard"
String imageType = ".jpg";
File[] listFile = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
goTODir(listFile[i]);
} else {
if (listFile[i].isHidden()){
if(listFile[i].getName().endsWith(imageType))
{
//add to your array list
}
}
}
}
}
}
String path = Environment.getExternalStorageDirectory().toString();
File dir = new File(path);
File listFile[] = dir.listFiles();
for (int i = 0; i < listFile.length; i++) {
if(listFile[i].getAbsolutePath().contains("your hidden folder name")){
File dirtest = new File(listFile[i].getAbsolutePath());
File listFiletest[] = dirtest.listFiles();
for (int j = 0; j < listFiletest.length; j++) {
get all images from hidden folder
}
}
}
For Kotlin Lover
companion object {
const val FOLDER_PATH = "/YourFolder/.hideen/"
}
/**
* Method to get all Image Path
* #return [ArrayList]
* */
fun getImagePath(): ArrayList<String> {
// image path list
val list: ArrayList<String> = ArrayList()
// fetching file path from storage
val file = File(Environment.getExternalStorageDirectory().toString() + FOLDER_PATH)
val listFile = file.listFiles()
if (listFile != null && listFile.isNullOrEmpty()) {
Arrays.sort(listFile, LastModifiedFileComparator.LASTMODIFIED_REVERSE)
}
if (listFile != null) {
for (imgFile in listFile) {
if (
imgFile.name.endsWith(".jpg")
|| imgFile.name.endsWith(".jpeg")
|| imgFile.name.endsWith(".png")
) {
val model : String = imgFile.absolutePath
list.add(model)
}
}
}
// return imgPath List
return list
}
i try to join two Contacts, a default Contact from the Default Address-Store, and a Contact of my own Provider.
I have the following code-snippet of the com.android.Contact app:
private interface JoinContactQuery {
String[] PROJECTION = {
RawContacts._ID,
RawContacts.CONTACT_ID,
RawContacts.NAME_VERIFIED,
RawContacts.DISPLAY_NAME_SOURCE,
};
String SELECTION = RawContacts.CONTACT_ID + "=? OR " + RawContacts.CONTACT_ID + "=?";
int _ID = 0;
int CONTACT_ID = 1;
int NAME_VERIFIED = 2;
int DISPLAY_NAME_SOURCE = 3;
}
Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
JoinContactQuery.PROJECTION,
JoinContactQuery.SELECTION,
new String[]{String.valueOf(contactId1), String.valueOf(contactId2)}, null);
if (c == null) {
Log.e(TAG, "Unable to open Contacts DB cursor");
return;
}
long rawContactIds[];
long verifiedNameRawContactId = -1;
try {
if (c.getCount() == 0) {
return;
}
int maxDisplayNameSource = -1;
rawContactIds = new long[c.getCount()];
for (int i = 0; i < rawContactIds.length; i++) {
c.moveToPosition(i);
long rawContactId = c.getLong(JoinContactQuery._ID);
rawContactIds[i] = rawContactId;
int nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if (nameSource > maxDisplayNameSource) {
maxDisplayNameSource = nameSource;
}
}
// Find an appropriate display name for the joined contact:
// if should have a higher DisplayNameSource or be the name
// of the original contact that we are joining with another.
if (writable) {
for (int i = 0; i < rawContactIds.length; i++) {
c.moveToPosition(i);
if (c.getLong(JoinContactQuery.CONTACT_ID) == contactId1) {
int nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if (nameSource == maxDisplayNameSource
&& (verifiedNameRawContactId == -1
|| c.getInt(JoinContactQuery.NAME_VERIFIED) != 0)) {
verifiedNameRawContactId = c.getLong(JoinContactQuery._ID);
}
}
}
}
} finally {
c.close();
}
// For each pair of raw contacts, insert an aggregation exception
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
for (int i = 0; i < rawContactIds.length; i++) {
for (int j = 0; j < rawContactIds.length; j++) {
if (i != j) {
buildJoinContactDiff(operations, rawContactIds[i], rawContactIds[j]);
}
}
}
// Mark the original contact as "name verified" to make sure that the contact
// display name does not change as a result of the join
if (verifiedNameRawContactId != -1) {
Builder builder = ContentProviderOperation.newUpdate(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, verifiedNameRawContactId));
builder.withValue("name_verified", 1);
operations.add(builder.build());
}
My Problem: The "name_verified" Field is removed on Android M (Preview 2). Whats the "correct" way to join two Contacts (and do not change the Name of the Contact)?
* EDIT / Solution *
Remove name_verified and set "IS_SUPER_PRIMARY" to content uri
//mark as SUPER PRIMARY
if (verifiedNameRawContactId != -1) {
operations.add(
ContentProviderOperation.newUpdate(ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, verifiedNameRawContactId))
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
.build());
}
The question is not quite clear to me but i think your are trying to join two contacts and one name is taking precedence over another but not the way you want it.
The correct way to join contacts is to add a row in this table and keep the type as TYPE_KEEP_TOGETHER. AggregationsExceptions table
If you want to keep the name of the first raw_contact mark the name record of the contact in Data table (StructuredName) as IS_SUPER_PRIMARY
IS_SUPER_PRIMARY
I want my App to list all directories and files on my FTP-Server. This is the code from How to list ftp directories with android?:
FTPFile[] files = null;
files = ftpClient.listDirectories();
String path = null;
for (int i = 0; i < files.length; i++) {
path = files[0].getName();
Log.d("CONNECT", "Directories: "+ files[i].getName());
}
FTPFile[] files2 = ftpClient.listFiles(topPath);
for (int j = 0; j < files2.length; j++) {
Log.d("CONNECT", "Below " + files[j].getName()
+ " is " + files2[j].getName());
}
}
Now this works for only for the first two layers. How can I manage to get as deep as necessary so I can list files that in folders that are in folders that are in folders and so on?
Thanks in advance :)
Now what I tried (not quite) recursively:
{ ...
FTPFile[] files = ftpClient.listFiles();
listContent(files);
.... }
private void listContent(FTPFile[] file) throws IOException {
FTPFile[] list = ftpClient.listDirectories();
if (list != null) {
for (FTPFile f : list) {
if (f.isDirectory()) {
Log.d(TAG, "directory: " + f.getName());
} else {
Log.d(TAG, "file: " + f.getName());
}
}
listContent(list);
} else return;
}
This code lets me get just the first layer of directories, the FTPFile[] is overwritten in ever new cycle.
How can I do that?
UPDATE:
Here's my solution. This code walks the whole content of the host-adress. Thanks to all who helped me:
private void listContent(String s) throws IOException {
try {
FTPFile[] ftpFiles = ftpClient.listFiles(s);
int length = ftpFiles.length;
for (int i = 0; i < length; i++) {
String name = ftpFiles[i].getName();
boolean isFile = ftpFiles[i].isFile();
if (isFile) {
Log.i(TAG, "File : " + name);
}
} else {
Log.i(TAG, "Directory : " + name);
if (ftpChangeDirectory(name) == true) {
Log.d("ftpChangeDirectory", name);
String newDir = ftpGetCurrentWorkingDirectory();
Log.d(TAG, "new Dir: " + newDir);
listContent(newDir);
}
}
}
ftpChangeDirectory("..");
String test = ftpGetCurrentWorkingDirectory();
Log.d("dirUp", test);
} catch (Exception e) {
e.printStackTrace();
}
}
I can't test it but something like this should work :
private void listAllFiles(String path) // path is the top folder to start the search
{
FTPFile[] files = ftpClient.listFiles(path); // Search all the files in the current directory
for (int j = 0; j < files.length; j++) {
Log.d("CONNECT", "Files: " + files[j].getName()); // Print the name of each files
}
FTPFile[] directories = ftpClient.listDirectories(path); // Search all the directories in the current directory
for (int i = 0; i < directories.length; i++) {
String dirPath = directories[i].getName();
Log.d("CONNECT", "Directories: "+ dirPath); // Print the path of a sub-directory
listAllFiles(dirPath); // Call recursively the method to display the files in the sub-directory
}
}
Anyway, i strongly recommend that you understand the code and check this link to learn more about recursivity.
I am currently working on a basic file browser for android. I have a working version for copying files, however as it works its way through directories it copies the files it finds. I want to change that so that I can find the total size of all files before starting to copy, as to help with a better progress bar.
If there is another way to find the total size of a directory and all its contents?
Here is my current version. I am having trouble changing this, I have tried using an arrayList however when I try to copy the files at the end, I think they are trying to copy in the wrong order.
public void copyDirectory(File sourceLocation , File targetLocation) throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create directory: " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create directory: " + directory.getAbsolutePath());
}
FileInputStream in = new FileInputStream(sourceLocation);
FileOutputStream out = new FileOutputStream(targetLocation);
long fileLength = sourceLocation.length();
byte[] buf = new byte[1024];
long total = 0;
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
total += len;
publishProgress((int) (total * 100 / fileLength));
}
in.close();
out.close();
}
}
Solution
jtwigg's answer should also work. I just thought I would add the solution I found. Can't answer my own question so I will put it here.
Looping through all the files in the directory and keeping a running total seems to work. Although it requires looping first for the size and again to actually copy the files. Just call getDirectorySize() with the file or directory you wish to copy before calling copyDirectory().
private void getDirectorySize(File sourceLocation) throws IOException {
if (sourceLocation.isDirectory()) {
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) {
getDirectorySize(new File(sourceLocation, children[i]));
}
} else {
totalFileSize += sourceLocation.length();
}
}
The function will require the global long totalFileSize, and then all that is required is to replace:
publishProgress((int) (total * 100 / fileLength));
with:
publishProgress((int) (total * 100 / totalFileSize));
If I understand you correctly, you wish to find the total size of all the files in the directory and then copy them.
I would create another function, something like:
public void beginCopy(File source, File destination)
{
ArrayList<PendingFile> filesToCopy = new ArrayList<PendingFile>();
long totalSize = copyDirectory(source, destination, filesToCopy);
// totalsize now contains the size of all the files
// files to copy now contains a list of source and destination files
// now modifying your copy method we can copy all the files
long totalThusFar = 0;
for (PendingFile pending : filesToCopy)
{
FileInputStream in = new FileInputStream(pending.source);
FileOutputStream out = new FileOutputStream(pending.destination);
long fileLength = sourceLocation.length();
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
totalThusFar += len;
publishProgress((int) (total * 100 / totalsize));
}
in.close();
out.close();
}
}
you would need a PendingFile class/structure just to hold both source and destinations. You will add them to the ArrayList in your copy method like this:
public long copyDirectory(File sourceLocation , File targetLocation, ArrayList list) throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw new IOException("Cannot create directory: " + targetLocation.getAbsolutePath());
}
String[] children = sourceLocation.list();
long totalSize = 0;
for (int i = 0; i < children.length; i++) {
totalSize += copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]), list);
return totalSize;
}
} else {
File directory = targetLocation.getParentFile();
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw new IOException("Cannot create directory: " + directory.getAbsolutePath());
}
list.add(new PendingFile(sourceLocation, targetLocation));
return sourceLocation.length;
}
}
I wrote all this just now so It probably won't work straight away but I think you should be able to get it working with this. Goodluck!