Upload *all* photos into Firebase - android

I am trying to create a backup photos app.
The app should upload all images into Firebase. When I start it the app uploads several photos perfectly but then crashes with this report.
java.util.concurrent.RejectedExecutionException: Task com.google.firebase.storage.StorageTask$8#e245bda rejected from java.util.concurrent.ThreadPoolExecutor#e13b80b[Running, pool size = 2, active threads = 2, queued tasks = 128, completed tasks = 0]
The code:
StorageReference storage_photos=FirebaseStorage.getInstance().getReference();
private void tryToTakePhotos() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
try {
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID};
final String orderBy = MediaStore.Images.Media._ID;
//Stores all the images from the gallery in Cursor
Cursor cursor = getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
null, orderBy);
int count = cursor.getCount();
int dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
Toast.makeText(this, "dd" + count, Toast.LENGTH_SHORT).show();
storage_photos = storage_photos.child(name + "---" + count + "photos");
for (int i = 0; i < count; i++) {
cursor.moveToPosition(i);
String filePath = cursor.getString(dataColumnIndex);
//Bitmap bitmap = BitmapFactory.decodeFile(filePath);
File file = new File(filePath);
Uri uri = Uri.fromFile(file);
StorageReference riversRef = storage_photos.child(uri.getLastPathSegment());
riversRef.putFile(uri);
}
cursor.close();
Calendar calendar = Calendar.getInstance();
firebase_takePhotos.setValue("taken at: " + calendar.get(Calendar.DAY_OF_MONTH) + "-"
+ (calendar.get(Calendar.MONTH) + 1) + "-"
+ calendar.get(Calendar.YEAR));
}catch (Exception e){
firebase_takePhotos.setValue(""+e);
}
}
}
}

I think the problem is with this line in loop
StorageReference riversRef = storage_photos.child(uri.getLastPathSegment());
Because for every item in loop you are making a whole new reference , resulting a queue of 128 tasks. And when you put file it asynchronously uploads the file so you are making alot of async tasks.

queued tasks = 128 indicates that you have reached maximum count of tasks
implementation before kitkat can queue only 128 tasks. Above which it will issue RejectedExecutionException. So I would suggest you reduce the number of task created.

The easiest and most efficient way to overcome this situation is by using Thread.sleep(SLEEP_TIME); after the putFile call along with a counter variable.
Example:
private int fileCounter = 0;
private final int FILE_BATCH_COUNT = 50; //50 files
private final int TIME_REQUIRED_FOR_BATCH_UPLOAD = 5*60000; //5 min, varies according to your internet speed
//...
private void yourFunction(){
//...
fileCounter = fileCounter + 1;
mStorageRef.putFile(fileUri).addOnSuccessListener(...).addOnFailiureListener(...);
if(fileCounter >= FILE_BATCH_COUNT){
Thread.sleep(TIME_REQUIRED_FOR_BATCH_UPLOAD);
fileCounter = 0;
}
}
FILE_BATCH_COUNT : The number of files after which you have to pause the thread to wait for the upload to complete.
TIME_REQUIRED_FOR_BATCH_UPLOAD : You have to find out your upload time in milliseconds for the said amount of files. (considering all are of similar size. other improvise.)

Related

Android Q, get a list of files with MediaStore ContentResolver

Per https://developer.android.com/training/data-storage/shared/documents-files#use-cases, once I targetSdk 29, the only way to get a list of files from the /Downloads directory is to use ACTION_OPEN_DOCUMENT_TREE, specifically:
// Using the Uri returned from Intent.ACTION_OPEN_DOCUMENT_TREE
DocumentFile dir = DocumentFile.fromTreeUri(context, uri);
DocumentFile[] files = dir.listFiles();
Which is fine, but it requires some explicit user action to select and approve it. (Though this will further get killed off if targetSdk 30/R.., but that's besides the point for now)
So how is https://play.google.com/store/apps/details?id=com.google.android.apps.nbu.files able to still get a list of files from /Downloads without that explicit selection/approval? (it is also targetSdk 29)
I tried these methods and they return empty results "uri empty":
// 1. uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI
// 2. uri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
cursor = context.getContentResolver().query(
uri, null, null, null,
DocumentsContract.Document.COLUMN_DISPLAY_NAME + " DESC");
if (cursor != null) {
if (cursor.moveToFirst()) { // targetSdk 28, I get these results
final int MAX_RESULTS = 50;
int colCount = cursor.getColumnCount();
int rowCount = cursor.getCount();
peek.append("uri[").append(rowCount).append(rowCount >= MAX_RESULTS ? "+]" : "]");
do {
peek.append("\n=======================================");
int colPos = cursor.getPosition();
if (colPos >= MAX_RESULTS) break;
for (int i = 0; i < colCount; i++) {
String colName = cursor.getColumnName(i);
String colVal = cursor.getString(i);
peek.append("\n").append(colPos).append(".").append(i).append(" ")
.append(colName).append("=").append(colVal);
}
} while (cursor.moveToNext());
} else { // targetSdk 29, nothing from the cursor/uri
peek.append("uri empty");
}
} else {
peek.append("cursor null");
}
*(note that this is on Emulator Android Q, I don't have a physical Q device)
And yes, READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE granted, and also tried android:requestLegacyExternalStorage="true"
And as expected, the old way to do this also doesn't work:
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
(Of course, when I switch back to targetSdk 28, all of the above work again.)
Am I missing some other API/method? Thanks!
EDIT: added query code

For loop loops before completing task of downloading image, resulting in unordered images

I'm trying to load an unspecified number of images and display them in the order they were taken however the method I'm using to loop through and download the images results in a random image order displayed even though it should be in order.
I did a simple test to see if the loop was initiating the next loop before completing the tasks and it seems like that is the case.
I've tried using the .addView method with index specification but that gives me an IndexOutOfBoundsException: index=1 count=0
for (int i = 1; i <= photoTakenAmount; i++) {
String photoName = "Photo_" + String.valueOf((i)) + ".jpg";
photoRef = firebaseStorage.getReference("users/" + mAuth.getUid() + "/Images/" + photoName);
photoRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
View photo_imageView = getLayoutInflater().inflate(R.layout.photo_imageview, mViewPhotoLayout, false);
mViewPhotoLayout.addView(photo_imageView);
ImageView imageView = photo_imageView.findViewById(R.id.photo_imageview);
Glide.with(mViewPhotoLayout).load(uri).into(imageView);
}
});
}
How can I get the images to load in order?
instead of using loops you can donwload the next image in onSuccess and make condition to stop the recursion.
this way ensures that each image will be loaded and showed in order
donwloadImage(0);
private downloadImage(int index){
String photoName = "Photo_" + String.valueOf((index)) + ".jpg";
photoRef = firebaseStorage.getReference("users/" + mAuth.getUid() + "/Images/" + photoName);
photoRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
View photo_imageView = getLayoutInflater().inflate(R.layout.photo_imageview, mViewPhotoLayout, false);
mViewPhotoLayout.addView(photo_imageView);
ImageView imageView = photo_imageView.findViewById(R.id.photo_imageview);
Glide.with(mViewPhotoLayout).load(uri).into(imageView);
index++;
if(index>photoTakenAmount)return;
else downloadImage(index);
}
});
}

Get multiple thumbnails from video

I'm using MediaMetadataRetriever to retrieve thumbnails at a specific time in video. This is how I achieve this:
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
try {
metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time = Long.valueOf(duration)/3;
Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
imgone.setImageBitmap(bitmap1);
}catch (Exception ex) {
Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
}
This returns a bitmap/thumbnail as expected, the problem is that if I want to get multiple thumbnails at different times in the video like this:
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
try {
metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time = Long.valueOf(duration)/3;
long time2 = time+time;
long time3 = time+time+time;
Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
Bitmap bitmap2 = metadataRetriever.getFrameAtTime(time2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
Bitmap bitmap3 = metadataRetriever.getFrameAtTime(time3,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
imgone.setImageBitmap(bitmap1);
imgtwo.setImageBitmap(bitmap2);
imgthree.setImageBitmap(bitmap3);
}catch (Exception ex) {
Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
}
Then it still only returns the same thumbnail, I'm not sure if it is because there is only one thumbnail available for the video or what, but I've tried different video files with the same result.
I've tried changing MediaMetadataRetriever.OPTION_CLOSEST_SYNC to all the available options but still the same result.
Im not sure if FFMPEG would be a better option for this?
Exactly a year later, I noticed that I never provided an answer.
In the original question I wanted to retrieve 3 thumbnails, I ended up retrieving 5. I also mentioned that I'm not sure if FFmpeg will be a suitable option, that's exactly what I used.
So, in OnCreate, I make sure that FFmpeg is supported and then I do the following:
if (FFmpeg.getInstance(getApplication()).isSupported()) {
#SuppressLint("SimpleDateFormat")
//ffmpeg expects the time format to be "00:00:00"
Format formatter = new SimpleDateFormat("00:" + "mm:ss.SS");
//Get the duration of the video
long duration = player.getDuration();
//Since I want 5 thumbnails, I divide the duration by 6 to get the first thumbnail position
long img1 = duration / 6;
//I format the first thumbnail time since ffmpeg expects "00:00:00" format
String firstTumbTime = formatter.format(img1);
//Scale the size of the thumbnail output (this can be improved/changed to your liking)
String scaledSize = displayMetrics.widthPixels / 7 + ":" + displayMetrics.heightPixels / 7;
//Set ffmpeg command (notice that I set vframes to one, since I only want 1 thumbnail/image)
String[] a = {"-ss", firstTumbTime, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb1.bmp"};
//start ffmpeg asynctask for the first thumbnail
ExecuteThumbFFMPEG(a);
} else {
Toast.makeText(TestNewPlayer.this, "Your device doesn't support FFMPEG...", Toast.LENGTH_SHORT).show();
}
The comments in the code above explains everything, now here is my ExecuteThumbFFMPEG method.
public void ExecuteThumbFFMPEG(String[] command) {
ffmpegImages = FFmpeg.getInstance(this).execute(command, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
//ffmpeg started
}
#Override
public void onProgress(String message) {
//get ffmpeg progress
}
#Override
public void onFailure(String message) {
//ffmpeg failed
}
#Override
public void onSuccess(String message) {
//first thumbnail saved successfully, now to get the other 4
//Scale the thumbnail output (Same as above)
String scaledSize = displayMetrics.widthPixels / 7 + ":" + displayMetrics.heightPixels / 7;
try {
//I first set the path/name for each thumbnail, this will also be used to check if the thumbnail is available or if we should get it
String imgPath1 = imageThumbsDirectory + "/" + "thumb1.bmp";
String imgPath2 = imageThumbsDirectory + "/" + "thumb2.bmp";
String imgPath3 = imageThumbsDirectory + "/" + "thumb3.bmp";
String imgPath4 = imageThumbsDirectory + "/" + "thumb4.bmp";
String imgPath5 = imageThumbsDirectory + "/" + "thumb5.bmp";
//Set the format again (same as above)
#SuppressLint("SimpleDateFormat")
Format formatter = new SimpleDateFormat("00:" + "mm:ss.SS");
//Get the length of the video
long duration = Player.getDuration();
//Divide the length of the video by 6 (same as above)
long time = duration / 6;
//Since I want 5 thumbnails evenly distributed throughout the video
//I use the video length divided by 6 to accomplish that
long img2 = time + time;
long img3 = time + time + time;
long img4 = time + time + time + time;
long img5 = time + time + time + time + time;
//Format the time (calculated above) for each thumbnail I want to retrieve
String Img2Timeformat = formatter.format(img2);
String Img3Timeformat = formatter.format(img3);
String Img4Timeformat = formatter.format(img4);
String Img5Timeformat = formatter.format(img5);
//Get reference to the thumbnails (to see if they have been created before)
File fileimgPath1 = new File(imgPath1);
File fileimgPath2 = new File(imgPath2);
File fileimgPath3 = new File(imgPath3);
File fileimgPath4 = new File(imgPath4);
File fileimgPath5 = new File(imgPath5);
//If thumbnail 1 exist and thumbnail 2 doesn't then we need to get thumbnail 2
if (fileimgPath1.exists() && !fileimgPath2.exists()) {
//Get/decode bitmap from the first thumbnail path to be able to set it to our ImageView that should hold the first thumbnail
Bitmap bmp1 = BitmapFactory.decodeFile(imgPath1);
//Set the first thumbnail to our first ImageView
imgone.setImageBitmap(bmp1);
//Set the ffmpeg command to retrieve the second thumbnail
String[] ffmpegCommandForThumb2 = {"-ss", Img2Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb2.bmp"};
//Start ffmpeg again, this time we will be getting thumbnail 2
ExecuteThumbFFMPEG(ffmpegCommandForThumb2);
}
//If thumbnail 2 exist and thumbnail 3 doesn't then we need to get thumbnail 3
if (fileimgPath2.exists() && !fileimgPath3.exists()) {
//Get/decode bitmap from the second thumbnail path to be able to set it to our ImageView that should hold the second thumbnail
Bitmap bmp2 = BitmapFactory.decodeFile(imgPath2);
//Set the second thumbnail to our second ImageView
imgTwo.setImageBitmap(bmp2);
//Set the ffmpeg command to retrieve the third thumbnail
String[] ffmpegCommandForThumb3 = {"-ss", Img3Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb3.bmp"};
//Start ffmpeg again, this time we will be getting thumbnail 3
ExecuteThumbFFMPEG(ffmpegCommandForThumb3);
}
////If thumbnail 3 exist and thumbnail 4 doesn't then we need to get thumbnail 4
if (fileimgPath3.exists() && !fileimgPath4.exists()) {
//Get/decode bitmap from the third thumbnail path to be able to set it to our ImageView that should hold the third thumbnail
Bitmap bmp3 = BitmapFactory.decodeFile(imgPath3);
//Set the third thumbnail to our third ImageView
imgThree.setImageBitmap(bmp3);
//Set the ffmpeg command to retrieve the fourth thumbnail
String[] ffmpegCommandForThumb4 = {"-ss", Img4Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb4.bmp"};
//Start ffmpeg again, this time we will be getting thumbnail 4
ExecuteThumbFFMPEG(ffmpegCommandForThumb4);
}
////If thumbnail 4 exist and thumbnail 5 doesn't then we need to get thumbnail 5
if (fileimgPath4.exists() && !fileimgPath5.exists()) {
//Get/decode bitmap from the first fourth path to be able to set it to our ImageView that should hold the fourth thumbnail
Bitmap bmp4 = BitmapFactory.decodeFile(imgPath4);
//Set the fourth thumbnail to our fourth ImageView
imgFour.setImageBitmap(bmp4);
//Set the ffmpeg command to retrieve the last thumbnail
String[] ffmpegCommandForThumb5 = {"-ss", Img5Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb5.bmp"};
//Start ffmpeg again, this time we will be getting thumbnail 5
ExecuteThumbFFMPEG(ffmpegCommandForThumb5);
}
//If thumbnail 5 exist, then we are done and we need to set it to our ImageView
if (fileimgPath5.exists()) {
Bitmap bmp5 = BitmapFactory.decodeFile(imgPath5);
imgFive.setImageBitmap(bmp5);
}
} catch (Exception ex) {
Toast.makeText(Player.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFinish() {
//ffmpeg is done
}
});
}
When the user back out of the Activity or OnDestroy gets called, all the thumbnails should be deleted, I do this by calling the following method:
DeleteThumbs.deleteAllThumbnails(getBaseContext());
Here is the DeleteThumbs class for deleting all the thumbnails/images
class DeleteThumbs {
#SuppressWarnings("unused")
static void deleteAllThumbnails(Context baseContext){
//Directory where all the thumbnails are stored
File imageThumbsDirectory = baseContext.getExternalFilesDir("ThumbTemp");
//Path to each thumbnail
File f1 = new File(imageThumbsDirectory + "/" + "thumb1.bmp");
File f2 = new File(imageThumbsDirectory + "/" + "thumb2.bmp");
File f3 = new File(imageThumbsDirectory + "/" + "thumb3.bmp");
File f4 = new File(imageThumbsDirectory + "/" + "thumb4.bmp");
File f5 = new File(imageThumbsDirectory + "/" + "thumb5.bmp");
boolean d1 = f1.delete();
boolean d2 = f2.delete();
boolean d3 = f3.delete();
boolean d4 = f4.delete();
boolean d5 = f5.delete();
}
}
Since we know the name of each thumbnail, it's easy to delete them all at once.
This provides me with 5 thumbnail images that are scaled to reduce loading time into the ImageView's. Because I divided the duration of the video by 6, I get 5 images that are evenly "distributed" throughout the video.
NOTE:
This can be improved by caching the images into memory or using a library like picasso or glide to handle the image loading for us.
Try this one
public void detectBitmapFromVideo(int secondcount, int framecount, String videoPath) {
//int fps = 800000 / framecount;
int delta_time = secondcount * 1000000; //in microsecs
//FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
//mmr.setDataSource(videoPath);
//String s_duration = mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION);
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(videoPath);
int duration = getVideoDuration(mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
//int duration = getVideoDuration(s_duration);
ArrayList<Frame> frames = new ArrayList<Frame>();
//Log.e("Duration ", "Duration = " + duration + " Delta time = " + delta_time);
for (int i = 0; i <= duration; i += delta_time) {
Bitmap bmFrame = mediaMetadataRetriever.getFrameAtTime(i);
//unit in microsecond
if (bmFrame == null) {
//Log.e(TAG, "frame image " + bmFrame.toString());
continue;
}
//saveBitmapImage(bmFrame,i+"");
frames.add(new Frame.Builder().setBitmap(bmFrame).build());
/*Bitmap frame_orig = mmr.getFrameAtTime(i, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
if (frame_orig == null) {
continue;
}
frames.add(new Frame.Builder().setBitmap(rotateBitmap(frame_orig, 90f)).build());
//Log.e("Faces Detected", "Face detection on going duration = " + duration + " Deleta time = " + i);
}
}

How can insert a lot of items with ContentResolver fast

I'm trying to add words to user dictionary in bulks (tens of thousands of words).
I've tried to
Scanner scanner = new Scanner(file);
int counter = 0;
while(scanner.hasNextLine()) {
String word = scanner.nextLine();
UserDictionary.Words.addWord(getBaseContext(), word, 255, null, Locale.getDefault());
setProgress((float) counter++ * 100 / linesCount);
}
and I've also tried bulkinsert
ArrayList<String> words = new ArrayList<String>(capacity);
int counter = 0;
while(scanner.hasNextLine()) {
words.add(scanner.nextLine());
if (words.size() >= capacity) {
MyUserDictionary.addWords(getBaseContext(), words, Locale.getDefault());
words.clear();
setProgress((float) counter * 100 / linesCount);
}
counter++;
}
if (!words.isEmpty()) {
MyUserDictionary.addWords(getBaseContext(), words, Locale.getDefault());
}
And I've tried applyBatch.
All this method results with very long running time.
I know that sqlite can do better with transactions.
Do you know more faster way to do it?
EDIT1:
final ContentResolver resolver = context.getContentResolver();
final int COLUMN_COUNT = 5;
List<ContentValues> valueses = new ArrayList<ContentValues>(words.size());
for (String word: words) {
ContentValues values = new ContentValues(COLUMN_COUNT);
values.put(UserDictionary.Words.WORD, word);
values.put(UserDictionary.Words.FREQUENCY, DEFAULT_FREQUENCY);
values.put(UserDictionary.Words.LOCALE, null == locale ? null : locale.toString());
values.put(UserDictionary.Words.APP_ID, 0); // TODO: Get App UID
values.put(UserDictionary.Words.SHORTCUT, "");
valueses.add(values);
}
resolver.bulkInsert(UserDictionary.Words.CONTENT_URI, valueses.toArray(new ContentValues[valueses.size()]));

too much time in reading sms from database and storing it in to text file

I'm reading sms record from database and write them into text file. But it takes too much time 3 to 4 mins to read n write 3500 records. If records are much more than that it takes plenty of time which is not appreciable. My code is:
final Cursor cur1 = c.getContentResolver().query(Uri.parse("content://sms/"), null, null, null, "date ASC");
final int size = cur1.getCount();
final int sleeptimer = size;
final SMS [] sms = new SMS[size];
final String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator + "account.txt";
FileWriter fw = null;
try {
fw = new FileWriter(baseDir);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final BufferedWriter writer = new BufferedWriter(fw);
Thread myThread = new Thread()
{
public void run()
{
try
{
int currentwait = 0;
int j=0;
while(currentwait < sleeptimer)
{
sleep(200);
currentwait+=200;
for(int i = 0 ; i < 200 ; i++)
{
if(!cur1.moveToNext())
{
break;
}
ContactInfo p = new ContactInfo();
String content = cur1.getString(cur1.getColumnIndex("body"));
String number = cur1.getString(cur1.getColumnIndex("address"));
long date = cur1.getLong(cur1.getColumnIndex("date"));
String protocol = cur1.getString(cur1.getColumnIndex("protocol"));
String name = p.getName(number, c);
String type = null;
Calendar cal=Calendar.getInstance();
cal.clear();
cal.setTimeInMillis(date);
String date_time=String.format("%1$te %1$tB %1$tY,%1$tI:%1$tM:%1$tS %1$Tp",cal);
if( protocol == null )
{
type = "Outbox";
}
else
type = "Inbox";
try{
writer.write("Type: " + type);
writer.newLine();
writer.write("Name: " + number+"<"+name+">");
writer.newLine();
writer.write("Date: " + date_time);
writer.newLine();
writer.write("Content: " + content);
writer.newLine();
writer.newLine();
} catch (IOException e) {
Log.i("INFO", e.getMessage().toString());
}
//Log.i("INFO", content+" "+j);
sms[j] = new SMS(type , name , number , date_time , content );
j++;
}
}
}
catch(Exception e)
{
}
finally{
try{
writer.flush();
writer.close();
}
catch (Exception e) {
}
uploadtoserver(baseDir);
}
}
};
myThread.start();
any idea to improve it ???thanks :)))
Just remove this line:
sleep(200);
Call setMaxSqlCacheSize to increase the cache size. Default is 10. Try setting 20 first and see whether the time reduces to half..
Or/And
You can execute this sqlite query before performing any operation on db and see if that improves the speed. Changing the temp store to memory should improve the read write speed..
PRAGMA temp_store = 2; /* 0 | DEFAULT | 1 | FILE | 2 | MEMORY; */
When temp_store is MEMORY (2) temporary tables and indices are kept in as if they were pure in-memory databases memory
Also
PRAGMA page_size = bytes;
Query or set the page size of the database. The page size must be a power of two between 512 and 65536 inclusive.
Probably you can pass these statements either to execSQL(String sql) or to query(). Try and let me know how it works.
Check out other PRAGMAs that Sqlite supports: http://www.sqlite.org/
Update:
From documentation of query API:
For best performance, the caller should follow these guidelines:
Provide an explicit projection, to prevent reading data from storage that aren't going to be used.
Use question mark parameter markers such as 'phone=?' instead of explicit values in the selection parameter, so that queries that differ only by those values will be recognized as the same for caching purposes.

Categories

Resources