I am using a DownloadManager to handle a download in my application, I would like to notify the user when the download is completed.
I am using the folowing code that is working well
public void downloaddownload(View v){
View v2 = (View) v.getParent();
TextView urlView = (TextView) v2.findViewById(R.id.url);
String urlString = (String) urlView.getText().toString();
TextView artistView2 = (TextView) v2.findViewById(R.id.artist);
final String artistString = (String) artistView2.getText().toString();
TextView titleView2 = (TextView) v2.findViewById(R.id.title);
final String titleString = (String) titleView2.getText().toString();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(urlString));
request.setDescription(titleString);
request.setTitle(artistString);
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC + "/folder", titleString + " - " + artistString + ".mp3");
Toast.makeText(mainContext, "Downloading " + titleString + " - " + artistString, Toast.LENGTH_SHORT).show();
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
onComplete = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(mainContext, "Download \" " + titleString + " - " + artistString + "\" completed", Toast.LENGTH_LONG).show();
}
};
registerReceiver(onComplete, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
The problem is that the onReceive method is called for previous downloads too.
Let's say I download a.mp3, b.mp3 and c.mp3, when a.mp3 is completed I recieve a.mp3 completed, when b.mp3 is completed I recieve a.mp3 is completed, then a new toast b.mp3 is completed...
How could I prevent this? thank you.
Yo are registering a BroadcastReceiver each time you download a file. That means, the second time you download a file, you'll have two receivers registered. You should probably unregister them using unregisterReceiver() after the work is done (probably in onReceive()).
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(downloadId);
Cursor cur = manager.query(query);
if (cur.moveToFirst()) {
int columnIndex = cur.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == cur.getInt(columnIndex)) {
titleString=cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_TITLE));}
you should use this to get your title string for individual downloads . because every download have their own id . I know Answer is too late but it may help for others in future...
Related
In my application(which is run on a couple of type of tv-boxes from same manufacturer and all deviecs are rooted) I do check last version of my application from a server of my own and if there is a new version available, I download the APK file and try to install it using pm install command.
Though I've never started any activity to install the APK, it automatically opens the activity from intent Intent intent = new Intent(Intent.ACTION_VIEW);.
I've never used Intent.ACTION_VIEW in my whole project, so I assume that the android DownloadManager opens this activity automatically, and I want to stop it from doing so. Any idea how?
Here is my code:
//this is the method where I download the apk
//I'm putting only the important parts to make the question as short as possible
private void downloadApk() {
if (status == State.DOWNLOADING)
return;
setStatus(State.DOWNLOADING);
String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
String fileName = appType + versionInfo.getVersionName() + ".apk";
destination += fileName;
Uri uri = Uri.parse("file://" + destination);
String url = versionInfo.getUrl();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Downloading new Hub version");
request.setTitle("Downloading");
request.setDestinationUri(uri);
downloadId = manager.enqueue(request);
monitorDownloadPercentage();
mContext.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
This method only calculates how much of the file is downloaded in percentage and calls the callback with the value. This calculated value, on it's path updates one ProgressBar and gets set as the text of a TextView.
private void monitorDownloadPercentage() {
new Thread(new Runnable() {
#Override
public void run() {
downloading = true;
while (downloading) {
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadId);
Cursor cursor = manager.query(q);
cursor.moveToFirst();
int bytes_downloaded = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.
getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (upgradeStateListener != null) {
upgradeStateListener.onDownloading((float) bytes_downloaded / bytes_total * 100);
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
}
}
}).start();
}
This is the broadcast receiver which gets fired when download is completed. And I'm sure this broadcast doesn't cause my problem since the only place in the code where could cause it is the onDownloadCompleted() method(which installs the APK using root privileges and I've commented all of it's body and it still pops up the activity.
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
final Cursor cursor = manager.query( new DownloadManager.Query().setFilterById(downloadId));
if (cursor.moveToFirst()) {
Uri uri ;
final String downloadedTo = cursor.getString(
cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
uri = Uri.parse(downloadedTo);
Log.d(TAG, "onReceive: it's ok " + uri.getPath());
upgradeStateListener.onDownloadCompleted(uri.getPath());
}
setStatus(State.DOWNLOADED);
mContext.unregisterReceiver(this);
}
};
I try, to check if this file exists after i downloaded it, but its says to me that is doesnt exist
#Override
public void handleResult(Result result)
{
myResult = result;
dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(result.getText());
DownloadManager.Request request = new DownloadManager.Request(uri);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
String nameOfFile = URLUtil.guessFileName(result.getText(),null, MimeTypeMap.getFileExtensionFromUrl(result.getText()));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, nameOfFile);
dm.enqueue(request);
String erg = "";
File mPath = new File((Environment.DIRECTORY_DOWNLOADS + "/" + nameOfFile));
if (mPath.getAbsoluteFile().exists()) {
erg = "existiert";
}else
{
erg = "existiert nicht";
}
}
The downloading process is happening on background. So after enqueue() your file doesn't exist cause it's not downloaded yet.
You just need to register BroadcastReceiver with this
ACTION_DOWNLOAD_COMPLETE intent filter. And DownloadManager will broadcast when downloads complete. See documentation here: https://developer.android.com/reference/android/app/DownloadManager.html#ACTION_DOWNLOAD_COMPLETE
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!
I have followed twitter fabric log in and everything is working fine except for the part where i try to post a tweet. When i execute this following code i need to login again, so it seems like i have to check an access token or some, but i have no idea and can't find how to do that.
#Override
public void onCreate(Bundle savedInstanceState) {
//initialize facebook sdk
FacebookSdk.sdkInitialize(getActivity().getApplicationContext());
super.onCreate(savedInstanceState);
TwitterSession session = Twitter.getSessionManager().getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
if (token != null ) {
Log.d(TAG, "twitter token" + token);
}
if (secret != null ) {
Log.d(TAG, "twitter secret" + secret);
}
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this.getActivity(), new TwitterCore(authConfig), new TweetComposer());
}
then i am using a function to post the tweet
public void TwitterSharing() {
Log.d(TAG, "Running twitter share");
Log.d(TAG, "Share on twitter 1: " + sport);
Log.d(TAG, "Share on twitter 2: " + speed);
Log.d(TAG, "Share on twitter 3: " + distance);
Log.d(TAG, "Share on twitter 4: " + date);
Log.d(TAG, "Shared image url: " + sharedImage);
TweetComposer.Builder builder = new TweetComposer.Builder(this.getActivity())
.text("just setting up my Fabric.")
.image(Uri.parse(sharedImage));
builder.show();
}
It all works but on the web page it is loading i need to login again, that should not happen but i have no idea how.
Thanks for any input.
For that, you need to make an Activity as the launcher activity. Let's call it DispatchActivity
public class DispatchActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState){
This returns true if user is logged in.
boolean isLoggedIn = mSharedPreferences.getBoolean(PREF_KEY_TWITTER_LOGIN, false);
if (isLoggedIn){
//User is logged in, take him to your activity
Intent i = new Intent(this,yourMainActivity.class);
this.startActivity(i);
}
else{
//User is not logged in, take him to your SignIn activity
Intent i = new Intent(this,SignUp.class);
this.startActivity(i);
}
}
}
Remember to make this your launcher activity, and don't create a layout file for it.
my android application freezes for a few seconds when i try to send my database file to my remote server, is there anyway i can set this as a background thread using multithreading or another such feature?
this is the code for the dialog box that appears to ask me if i want to send
public void showYesNoBox(){
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked
SendData();
finish();//go back to the previous Activity
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
break;
case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
finish();//go back to the previous Activity
overridePendingTransition(R.anim.fadein, R.anim.fadeout);
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this, AlertDialog.THEME_HOLO_DARK);
builder.setMessage("Do you want to send the data now?");
builder.setPositiveButton("Yes", dialogClickListener);
builder.setNegativeButton("No", dialogClickListener);
builder.show();
}
and here is the code it executes when i click the "Yes" button
public void SendData() {
File path = getDatabasePath(DataBaseHelper.DATABASE_NAME);
if (path.exists())
copyDatabase(path);
}
/**
* Copy the database to the sdcard
* #param file
*/
private void copyDatabase(File file) {
SimpleDateFormat dateFormat1 = new SimpleDateFormat("ddMMyy-HHmmss");
String dateString = dateFormat1.format(new Date());
String pathdest = getDir().getAbsolutePath() + Configuration.LOST_FOLDER + "/Database/";
String pathdir = pathdest;
File dir = new File(pathdir);
if (!dir.exists())
dir.mkdirs();
String namefile = file.getName();
int pos = namefile.lastIndexOf('.');
if (pos != -1) {
String ext = namefile.substring(pos + 1);
String name = namefile.substring(0, pos - 1);
pathdest += name;
pathdest += "_" + dateString;
pathdest += ext;
} else {
pathdest += namefile;
pathdest += "_" + dateString;
}
File filedest = new File(pathdest);
try {
if (filedest.createNewFile())
copyFile(file.getAbsolutePath(), pathdest);
} catch (IOException e) {
e.printStackTrace();
}
}
any help with this problem would be greatly appreciated as while the problem doesn't prevent the user from being able to send the data it is anoying to be stuck on one screen for a few seconds while it attempts to execute the action.
while the problem doesn't prevent the user from being able to send the data it is anoying to be stuck on one screen for a few seconds while it attempts to execute the action.
You can see AsyncTask. Its for the same purposes. User need not be stuck on UI when you want to do long running processes including taking to server, doing database stuff etc. This can be done in the background using AsyncTask. There are many good tutorials out there. Just Google it. Checkout Android Background Processing with Threads, Handlers and AsyncTask - Tutorial and What arguments are passed into AsyncTask<arg1, arg2, arg3>? . Hope this helps.
I've been using asynctask for handling all the processes I want to do in the background.
AsyncTask
Use all network operations in AsyncTask
like the below example
private class UploadTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
// upload task
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Once created, a task is executed very simply:
new UploadTask().execute(url1, url2, url3);