Android app lags while a big file is downloaded - java

I'm using Fast-Android-Networking library in my android app to download file through it.
For files less than 15 megabytes, my code works fine. But, when I try downloading files with more than 20 megabytes of length, the application and also the target device lags.
When I tested with my old Lenovo A319 which has 512mb of RAM, I've found the problem and thought it must be an hardware problem.
But, after testing the application in Lenovo A6000, Samsung J1 4G, Motorola Moto G Turbo and LYF Water 11, I came to this decision that the application is lagging on all devices and only while the file is being downloaded.
I can't understand why this problem is happening. I've also checked the logcat but found nothing that can help me to understand the root of the problem.
Any idea?
Some of my code :
AndroidNetworking.download(link, Environment.getExternalStorageDirectory().getPath() + "/ABCD", title + "."+fileExtension)
.setTag("Download: " + title)
.setPriority(Priority.HIGH)
.build()
.setDownloadProgressListener(new DownloadProgressListener() {
#Override
public void onProgress(long bytesDownloaded, long totalBytes) {
int percentage = (int) Math.floor(bytesDownloaded * 100.0 / totalBytes);
System.out.println(percentage);
//I'm using Notification to report progress to user.
mBuilder.setProgress(100, percentage, false);
mNotifyManager.notify(id, mBuilder.build());
}
})
.startDownload(new DownloadListener() {
#Override
public void onDownloadComplete() {
if (file.length() < 500000) {
Snackbar.make(mView, "Download Error", Snackbar.LENGTH_LONG).show();
mBuilder.setContentText("Download Error!").setProgress(0, 0, false);
mNotifyManager.notify(id, mBuilder.build());
} else {
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setDataAndType(path, getMimeType(path.toString()));
PendingIntent notifyPIntent = PendingIntent.getActivity(mContext.getApplicationContext(), 0, intent, 0);
mBuilder.setContentIntent(notifyPIntent);
mBuilder.setContentTitle("Download Completed")
.setContentText("Download complete! - Click To Play")
.setProgress(0, 0, false);
mNotifyManager.notify(id, mBuilder.build());
Snackbar.make(mView, "Download Completed : " + title + "."+fileExtension, Snackbar.LENGTH_LONG).setAction("Play Now", new View.OnClickListener() {
#Override
public void onClick(View v) {
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setDataAndType(path, getMimeType(path.toString()));
mContext.startActivity(intent);
}
}).show();
}
}
#Override
public void onError(ANError error) {
Snackbar.make(mView, "Download Error : " + error.toString(), Snackbar.LENGTH_LONG).show();
error.printStackTrace();
mBuilder.setContentText("Download Error!");
mBuilder.setProgress(0, 0, false);
mNotifyManager.notify(id, mBuilder.build());
}
});

Based on this issue, library has critical problems in memory usage area.

Related

Display a download failed notification using Download Manager for Android TV?

I,m trying to build my first app using Android Studio.Its for Android TV. I can't figure out how to notify the user if a download fails.
It's an Android TV app so threes no status bar to display download managers progress in.The code as is displays results from any button click including ones from mainactivity2. However obviously the way I have it it displays the same message when receiving ACTION_DOWNLOAD_COMPLETE regardless of success or failure.
I've tried many methods but most assume I have a better grasp on coding than I do, or had many errors I'm not knowledgeable enough to understand, so I've been unable to incorporate them.
I did manage to get a progress bar to work but with the files being less than a megabyte, and only providing an empty progress bar when download was unsuccessfull, it was less than ideal.
I'm hoping someone can help me display failure or success.
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(MainActivity.this, "Your download is complete.", Toast.LENGTH_SHORT).show();
}
};
#Override
public void onClick(View view) {
registerReceiver(receiver, filter);
int id = view.getId();
if (id == R.id.myfile) {
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request1 = new DownloadManager.Request(
Uri.parse("https://myurl.zip"));
request1.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "/mydir/myfile.zip");
dm.enqueue(request1);
Toast.makeText(MainActivity.this, "Your chose myfile.zip", Toast.LENGTH_SHORT).show();
} else if (id == R.id.myfile2) {
DownloadManager dm;
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request2 = new DownloadManager.Request(
Uri.parse("https://myurl2.zip"));
request2.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "/mydir2/myfile2.zip");
dm.enqueue(request2);
Toast.makeText(MainActivity.this, "You chose myfile2.zip.", Toast.LENGTH_SHORT).show();
}
}
}
I thought I should post my resolution to my problem in hopes it may assist someone with a similar situation.
I ultimately abandoned DownloadManager in favor of the fast Android networking library from https://github.com/amitshekhariitbhu/Fast-Android-Networking.
I'm sure there was a way to accomplish my goal with DownloadManager but this worked for me.
Here's an Example of receiving a success or failure toast when downloading a file. Progress status is unused in this example.
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.example) {
Toast.makeText(MainActivity.this, "You chose The example.", Toast.LENGTH_SHORT).show();
AndroidNetworking.download("https://example.github.io/repository.0.3.1.zip",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/example", "/repository.0.3.1.zip")
.setTag("Download")
.setPriority(Priority.MEDIUM)
.build()
.setDownloadProgressListener(new DownloadProgressListener() {
#Override
public void onProgress(long bytesDownloaded, long totalBytes) {
}
})
.startDownload(new DownloadListener() {
#Override
public void onDownloadComplete() {
Toast.makeText(MainActivity.this, "The download is complete.", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(ANError error) {
Toast.makeText(MainActivity.this, "The download failed.", Toast.LENGTH_SHORT).show();
}
});

How do I not show empty 0 B files when I use Intent.ACTION_GET_CONTENT?

In my app I need to pick images from storage and display them on screen. I'm using an Intent to do this for me. I have posted my code to do this below.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
Intent.createChooser(intent, "Select a File to Upload"),
FILE_SELECT_CODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
The issue is that when the intent opens, I see a bunch of empty files of size 0 B. These files are not visible in the File Manager tool on my phone (where I'm testing my app). Is there any way to fix this - either by deleting those empty files or by having the intent ignore them?
Note: I don't know if this is helpful, but the images above are generated by my app, which uses Camera to capture and save images and later load them back through the file picker. The image with the preview is visible in the File Manager and is not 0 B, but the others are invisible.
Screenshot of file picker
Edit: Here's the code I'm using to capture images using camera and save them.
public void captureImageAction()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED ||
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
String[] permission = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permission, PERMISSION_CODE);
} else {
openCamera();
}
} else {
openCamera();
}
}
private void openCamera() {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From Camera");
image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
int IMAGE_CAPTURE_CODE = 1001;
startActivityForResult(cameraIntent, IMAGE_CAPTURE_CODE);
}

Android Studio - Do not close app when locking phone

I've searched a lot on the Internet trying to find an answer for my needs, but in vain.
Here's my problem: I'm making an app that "counts time". The user press "Start" button and then go away for pretty much a long time of work on the field (2h,even more).
Then he has to come back and press the "End" button to show he have finished his job. My app then computes how long has he worked ( and some other thing I wont explain here ), and the user send the total of his work hours by mails to his superior.
Problem is :
-First my app is closed when the phone is locked and so the Start time is lost and calculations are off.
-Second : the user has to repeat the Start-End cycle many times a day, so i have a way of computing the total work hours, but again it's lost when the app is closed
So I'm opened to any idea/suggestions to solve my issues :)
Oh and I have Huawei P8 Lite for info, if that matters in anyway
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext=MainActivity.this;
mTimeListenerD.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the Start time
setDebutTime();
checkEnabled();
writeToFile(sName,sTempsTravail);
}
});
mTimeListenerF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { //Button to set the End Time
setFinTime();
checkEnabled();
getHeureSupp(mTimeD, mTimeF);
FindSmallest(TimeRegister);
Clock();
writeToFile(sName,sTempsTravail);
readFromFile();
try {
copyFile(src,dst);
} catch (IOException e) {
e.printStackTrace();
}
Reinit();
}
});
mMail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMail();
}
}); //Send data by mail
readFromFile();
getName();
checkEnabled();
}
public Calendar setDebutTime() { // Set the Start Time
mTimeD = Calendar.getInstance();
mTimeD.getTime();
//Toast.makeText(this, mTimeD.getTime().toString(), Toast.LENGTH_SHORT).show();
sDebut = mTimeD.get(Calendar.DAY_OF_MONTH) + "/" + mTimeD.get(Calendar.MONTH) + "/" + mTimeD.get(Calendar.YEAR) + "--" + mTimeD.get(Calendar.HOUR_OF_DAY) + ":" + mTimeD.get(Calendar.MINUTE) + ":" + mTimeD.get(Calendar.SECOND);
mGetTimeDebut.setText("" + sDebut);
start=true;
notif=false;
String pathToMyAttachedFile = "/Android/data/com.example.benjii.saphir_astreinte/files/Documents/SAPHIRAgent.csv"; //A changer
File root = Environment.getExternalStorageDirectory();
File file = new File(root, pathToMyAttachedFile);
boolean deleted =file.delete();
if(!deleted){file.delete();}
return mTimeD;
}
public Calendar setFinTime() { // set the End Time
mTimeF = Calendar.getInstance();
mTimeF.getTime();
// Toast.makeText(this, mTimeF.getTime().toString(), Toast.LENGTH_SHORT).show();
sFin = mTimeF.get(Calendar.DAY_OF_MONTH) + "/" + mTimeF.get(Calendar.MONTH) + "/" + mTimeF.get(Calendar.YEAR) + "--" + mTimeF.get(Calendar.HOUR_OF_DAY) + ":" + mTimeF.get(Calendar.MINUTE) + ":" + mTimeF.get(Calendar.SECOND);
mGetTimeFin.setText("" + sFin);
start=false;
notif=true;
return mTimeF;
}
Then I have some function to do the calculations I need with the worked hours.
Once it is done I write it into a file on Internal Storage but then copy it to external storage:
public void writeToFile(String Name,String TempsTravail){ //File that'll be send by mail
try{
OutputStreamWriter StrW= new OutputStreamWriter(this.openFileOutput("SAPHIRAgent.csv", Context.MODE_PRIVATE));
src=mContext.getFilesDir().getAbsolutePath()+"/file.csv";
dst=mContext.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()+"/file.csv";
//Toast.makeText(this,dst,Toast.LENGTH_LONG).show();
StrW.append(Name);
StrW.append(separator);
StrW.append(sDebut);
StrW.append(separator);
StrW.append(sFin);
StrW.append(separator);
StrW.append(TempsTravail);
StrW.append("\n"+mTempsTravail);
if(cool){
StrW.append(separator);
StrW.append(sCool);
}
if(warning){
StrW.append(separator);
StrW.append(sWarning);
}
if(critical){
StrW.append(separator);
StrW.append(sCritical);
}
StrW.flush();
StrW.close();
}
catch (IOException e){
Log.e("ExceptionFile","Failed to write "+e.toString());
}
}
Then I send the file by mail:
public void sendMail(){ //SendMail function
Intent emailIntent = new Intent(Intent.ACTION_SEND);
final String[] to={"xxx#gmail.com"};
final String subj="Sortie Agent "+sName;
final String body="Voir pièce jointe";
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_EMAIL, to);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subj);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
File root = Environment.getExternalStorageDirectory();
String pathToMyAttachedFile = "/Android/data/com.example.myapp/files/Documents/file.csv";
File file = new File(root, pathToMyAttachedFile);
//Toast.makeText(this,"RootPath "+root.getAbsolutePath(),Toast.LENGTH_LONG).show();
if (!file.exists() || !file.canRead()) {
Toast.makeText(this,"ToastError",Toast.LENGTH_LONG).show();
return;
}
Uri uri = Uri.fromFile(file);
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(emailIntent, "Choisissez votre application de Mail (Gmail,Outlook...)"));
}
But as I said, my app constantly closing is such an issue to my work, I hope you have any solutions !
Activity's are designed to stop once the phone sleeps.
What you need is a background service that runs always.
https://developer.android.com/training/run-background-service/create-service.html
http://www.vogella.com/tutorials/AndroidServices/article.html
So thanks to #Matthew Shearer, I've been able to fix my issues,learn many things about services and have a fully functionnal app on all phones, but Huawei.I learnt that Huawei phones had a specific function called "Protected Apps" which gave me many problems to keep my service alive.
But there is a solution here :
"Protected Apps" setting on Huawei phones, and how to handle it
Copy paste the code, use the ifHuaweiAlert() in the onCreate() and enjoy!

Parsing Error on downloading and running an .apk file

I have a feature in my app which allows the user to download a new version.
But my problem is when I start the intent which should start the installation proccess there is a message:
Parse error. There was a problem parsing the package
This is my code
Button button;
String urlApp = "example.com/app.apk"
String fileName = "app.apk";
DownloadManager downloadManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
File file = new File(Environment.DIRECTORY_DOWNLOADS, fileName);
if (file.exists()){
boolean deleted = file.delete();
Toast.makeText(getApplicationContext(), "Deleted", Toast.LENGTH_SHORT).show();
}
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(urlApp));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle("Click to update");
downloadManager.enqueue(request);
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
});
}
private void openFile() {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(new File(Environment.DIRECTORY_DOWNLOADS+"/"+fileName)),
"application/vnd.android.package-archive");
startActivity(install);
}
BroadcastReceiver onComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
openFile();
}
};
}
It's just for .apk files, .txt files work fine. There is neither a error on the logcat.
The deleting is also not working but this isn't my primary problem.
Thanks in advance :D
Sorry if this is a stupid problem but this is my first time working with the download manager
Ok, i finally solved it
Instead of:
install.setDataAndType(Uri.fromFile(new File(Environment.DIRECTORY_DOWNLOADS+"/"+fileName)),
"application/vnd.android.package-archive");
i used
install.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/"+fileName)),
"application/vnd.android.package-archive");
I have come across the same problem earlier.
Please check the Min API level for your new Application version and the API level of the device you are using.

How to crop image in java for android with OS Lollipop

I have the following code for cropping images. It's working perfectly in android version 4 or OS Kitkat, but its not working on Android version 5 or OS Lollipop.
I've already searched the whole world but couldn't find the answer...
Here's my code:
In OS Kitkat: this list variable return a value. but,
In OS Lollipop: this list variable return a empty arraylist.
final ArrayList<CropOption> cropOptions = new ArrayList<CropOption>();
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
List<ResolveInfo> list = getPackageManager().queryIntentActivities( intent, 0 );
PackageManager test = getPackageManager();
int size = list.size();
if (size == 0) {
Toast.makeText(this, "Can not find image crop app", Toast.LENGTH_SHORT).show();
return;
} else {
intent.setData(mCapturedImageURI);
intent.putExtra("outputX", 110);
intent.putExtra("outputY", 110);
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("scale", true);
intent.putExtra("return-data", true);
if (size == 1) {
Intent i = new Intent(intent);
ResolveInfo res = list.get(0);
i.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
startActivityForResult(i, CROP_FROM_CAMERA);
} else {
for (ResolveInfo res : list) {
final CropOption co = new CropOption();
co.title = getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
co.icon = getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
co.appIntent= new Intent(intent);
co.appIntent.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
cropOptions.add(co);
}
CropOptionAdapter adapter = new CropOptionAdapter(getApplicationContext(), cropOptions);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose Crop App");
builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int item ) {
startActivityForResult( cropOptions.get(item).appIntent, CROP_FROM_CAMERA);
}
});
builder.setOnCancelListener( new DialogInterface.OnCancelListener() {
#Override
public void onCancel( DialogInterface dialog ) {
if (mCapturedImageURI != null ) {
getContentResolver().delete(mCapturedImageURI, null, null );
mCapturedImageURI = null;
}
}
} );
AlertDialog alert = builder.create();
alert.show();
}
}
I had already given android.permission.MANAGE_DOCUMENTS permission. But facing the same issue. After searching a lot, i found the solution.
Here's a workaround, for the time being:
Intent mIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(mIntent, CHOOSE_IMAGE);
This forces the older image gallery to open instead of the new Kitkat documents view.
Now, you can get the Uri by calling the following in your onActivityResult:
Uri selectedImageURI = data.getData();
Hope this help to solve your problem.

Categories

Resources