Android File Download and custom notification display download progress

Source: Internet
Author: User


In the past few days, we have implemented an APK version update function, and found that it involves a lot of things. I have written the relevant content into a relatively independent category for future reference and share it with you. You are welcome to criticize and correct it.

The following classes are implemented:

(1) File Download: a custom class is designed. You only need to input a Handler, URLStr, storage path, and download function. Handler is mainly used for inter-thread communication and the progress bar in the new notification.

When handler sends a message to update the UI thread to display the progress, be sure not to send the message too frequently. The system will send the message after setting the counter for a certain period of time. Otherwise, the system may crash.

(2) Notification: Provides the default built-in form and custom Notification bar layout.

(3) Service: Background Service, startService Startup Mode



Package com. Example. The test;

Import the Java. IO. BufferedInputStream;
Import the Java. IO. The File;
Import the Java. IO. FileNotFoundException;
Import the Java. IO. FileOutputStream;
Import the Java. IO. IOException;
Import the Java. IO. InputStream;
The import java.net.HttpURLConnection;
The import java.net.MalformedURLException;

The import android. The annotation. SuppressLint;
The import android. OS. The Environment;
The import android. OS. Handler;
The import android. OS. The Message;
The import android. OS. StrictMode.
The import android. Util. Log;

@ SuppressLint (" NewApi ")
Public class DownFileThread implements Runnable {
Public final static int DOWNLOAD_COMPLETE = -2;
Public final static int DOWNLOAD_FAIL = -1;
Public final static String TAG = "DownFileThread";
Handler mHandler; // the incoming Handler is used to notify the download progress like an Activity or service
String urlStr; / / download URL
The File apkFile; // file save path
Boolean isFinished; // download completed
Boolean interupted = false; // whether to force the download thread to stop
Public DownFileThread(Handler Handler,String urlStr,String filePath)
{
The Log. I (TAG, urlStr);
Enclosing mHandler = handler;
Enclosing urlStr = urlStr;
ApkFile = new File (filePath);
IsFinished = false;
}
The public File getApkFile ()
{
If (isFinished)
Return apkFile;
The else
Return null;
}
Public Boolean isFinished () {
Return isFinished;
}

/ * *
* forced termination of file download
* /
Public void interuptThread ()
{
Interupted = true;
}

@ Override
Public void the run () {
// TODO auto-generated method stub
If (Environment. GetExternalStorageState (.) equals (
Environment. MEDIA_MOUNTED)) {
Java.net.URL url = null;
HttpURLConnection conn = null;
InputStream cost = null;
/ / if (DEVELOPER_MODE)
{
StrictMode. SetThreadPolicy (new StrictMode. ThreadPolicy. Builder ()
DetectDiskReads ()
DetectDiskWrites ()
DetectNetwork () / / or detectAll () for all detectable the problems
PenaltyLog ()
The build ());
StrictMode. SetVmPolicy (new StrictMode. VmPolicy. Builder ()
DetectLeakedSqlLiteObjects ()
DetectLeakedClosableObjects ()
PenaltyLog ()
PenaltyDeath ()
The build ());
}
Try {
Url = new java.net.URL (urlStr);
Conn = (HttpURLConnection) url. OpenConnection ();
Conn. SetConnectTimeout (5000);
Conn. SetReadTimeout (20000);
Cost = conn. GetInputStream ();
} catch (MalformedURLException e) {
The Log i. (TAG, "MalformedURLException");
E.p rintStackTrace ();
} catch (Exception e) {
Log. I (TAG, "failed to get input stream ");
E.p rintStackTrace ();
}
FileOutputStream fos = null;
Try {
Fos = new FileOutputStream (apkFile);
} catch (FileNotFoundException e) {
Log. I (TAG, "failed to get output stream: new FileOutputStream(apkFile);" );
E.p rintStackTrace ();
}
BufferedInputStream bis = new BufferedInputStream(iStream);
Byte [] buffer = new byte[1024];
Int len.
// gets the total length of the file
Int length = conn. GetContentLength ();
Double rate = 100 / length (double); // Max progress converted to 100
Int total = 0;
Int times = 0; // set the update frequency, frequent operation of the UI thread will cause the system to crash
Try {
Log. I ("threadStatus", "start downloading ");
While (false==interupted && (len = bis. Read (buffer))! = 1) {
Fos. Write (buffer, 0, len);
// gets the length that has been read

Total + = len;
Int p = (int) (total * rate);
The Log i. (" num ", rate + ", "+ +", "total + p).
If (times > = 512 | | p = = 100)
{/ *
This prevents the system from slowing down or even crashing due to frequent notifications.
Very important... * /
The Log i. (" time ", "time");
Times = 0;
The Message MSG = Message. Obtain ();
MSG. What = p;
MHandler. SendMessage (MSG);
}
Times++;
}
Fos. Close ();
The bis. Close ();
Cost. The close ();
If (total = = length)
{
IsFinished = true;
MHandler. SendEmptyMessage (DOWNLOAD_COMPLETE);
Log. I (TAG, "download finished ");
}
Log. I (TAG, "mandatory end of stream ");
/ / mhandler. SendEmptyMessage (4);
} catch (IOException e) {
Log. I (TAG, "exception ends ");
MHandler. SendEmptyMessage (DOWNLOAD_FAIL);
E.p rintStackTrace ();
}
}
The else
{
Log. I (TAG, "external memory card does not exist, download failed!" );
MHandler. SendEmptyMessage (DOWNLOAD_FAIL);
}
}
}

Package com. Example. The test;

The import android. App. Notification;
The import android. App. NotificationManager;
The import android. App. PendingIntent;
The import android. The content. The Context;
The import android. Widget. RemoteViews;
/ * *
* Notification class, which can use either the system's default Notification layout or a custom layout
*
* @ author lz
*
* /
Public class MyNotification {
Public final static int DOWNLOAD_COMPLETE = -2;
Public final static int DOWNLOAD_FAIL = -1;
The Context mContext; //Activity or Service context
Notification Notification; / / notification
NotificationManager nm;
String titleStr; // notification title
String contentStr; // notification content
PendingIntent contentIntent; // action after clicking the notification
Int notificationID; // the unique ID of the notification
Int iconID; // notification bar icon
Long the when = System. CurrentTimeMillis ();
RemoteViews remoteView = null; // custom notification bar view
/ * *
*
* @param context Activity or Service context
* @param contentIntent click on the action after notification
* unique identifier id for @param id notification
* /
Public MyNotification(Context Context,PendingIntent contentIntent,int id) {
// TODO auto-generated constructor stub
MContext = context;
NotificationID = id;
Enclosing contentIntent = contentIntent;
Enclosing the nm = (NotificationManager) mContext. GetSystemService (Context. NOTIFICATION_SERVICE);
}

/ * *
* displays custom notifications
* @param icoId custom view image ID
* @param titleStr notice column title
* @param layoutId custom layout file ID
* /
Public void showCustomizeNotification (int icoId, String titleStr, int layoutId) {
Enclosing titleStr = titleStr;
Notification = new notification (R.d rawable ic_launcher, titleStr, when);
Notification. The flags = notification. FLAG_ONLY_ALERT_ONCE;
Notification. The flags | = notification. FLAG_AUTO_CANCEL;
Notification. The contentIntent = this. ContentIntent;

// 1, create a custom message layout view.xml
// 2, use the RemoteViews method to define the image and text in the program code. Then pass the RemoteViews object to the contentView field
If (remoteView = = null)
{
RemoteView = new RemoteViews (mContext getPackageName (), layoutId);
RemoteView. SetImageViewResource (R.i d.i vNotification icoId);
RemoteView. SetTextViewText (R.i which vTitle titleStr);
RemoteView. SetTextViewText (R.i which vTip, "start download");
RemoteView. SetProgressBar (R.i d.p bNotification, 100, 0, false);
Notification. ContentView = remoteView;
}
Nm. Notify (notificationID, notification);
}
/ * *
* change the value of the progress bar in the custom layout file
* @param p progress value (0~100)
* /
Public void changeProgressStatus (int) p
{
If (notification contentView! = null)
{
If (p = = DOWNLOAD_FAIL)
Notification. ContentView. SetTextViewText (R.i which vTip, "download failed! ");
Else if (p = = 100)
Notification. ContentView. SetTextViewText (R.i which vTip, the download is complete, click "install");
The else
Notification. ContentView. SetTextViewText (R.i which vTip, "progress (%)" + p + ":");
Notification. ContentView. SetProgressBar (R.i d.p bNotification, 100, p, false);
}
Nm. Notify (notificationID, notification);
}
Public void changeContentIntent (PendingIntent intent)
{
Enclosing contentIntent = intent;
Notification. ContentIntent = intent;
}
/ * *
* displays system default format notifications
* @param iconId notification bar iconId
* @param title ext notification bar title
* @param contentStr notification bar content
* /
Public void showDefaultNotification(int iconId,String titleText,String contentStr) {
Enclosing titleStr = titleText;
Enclosing contentStr = contentStr;
Enclosing iconID = iconID;

Notification = new notification ();
Notification. TickerText = titleStr;
Notification. Icon = iconID;
Notification. The flags = notification. FLAG_INSISTENT;
Notification. The flags | = notification. FLAG_AUTO_CANCEL;
Notification. The contentIntent = this. ContentIntent;

// add sound effects
/ / notification. Defaults | = notification. DEFAULT_SOUND;

// add vibration, later learned to add vibration Permission: Virbate Permission
// mnotification. defaults |= notification. DEFAULT_VIBRATE;

// add status flag
//FLAG_AUTO_CANCEL this notice can be cleared by the clear button in the status bar
//FLAG_NO_CLEAR this notification can be cleared by the clear button in the status bar
//FLAG_ONGOING_EVENT notification placed at running
/ / FLAG_INSISTENT notice has been playing music effect
Notification. The flags = notification. FLAG_ONLY_ALERT_ONCE;
ChangeNotificationText (contentStr);
}
/ * *
* change the notification content of the default notification bar
* @ param content
* /
Public void changeNotificationText (String content)
{
Notification. SetLatestEventInfo (mContext titleStr, content, contentIntent);

// set the setLatestEventInfo method, otherwise the App will report an error exception
// NotificationManager mNotificationManager = (NotificationManager) getSystemService(context.notification_service);
// register this notice
// if the notification for the NOTIFICATION_ID already exists, information about the latest notification, such as tickerText, is displayed
Nm. Notify (notificationID, notification);
}

/ * *
* removal notice
* /
Public void removeNotification ()
{
// cancels only the Notification of the current Context
Nm. Cancel (notificationID);
}

}

Package com. Example. The test;

Import the Java. IO. The File;

The import android. App. Notification;
The import android. App. NotificationManager;
The import android. App. PendingIntent;
The import android. App. Service;
The import android. The content. The Context;
The import android. Content. Intent;
The import android.net.Uri;
The import android. OS. The Environment;
The import android. OS. Handler;
The import android. OS. IBinder;
The import android. OS. The Message;
The import android. The provider. Settings. Global;
The import android. Util. Log;

Public class DownloadServices extends Service {
Private final static int DOWNLOAD_COMPLETE = -2;
Private final static int DOWNLOAD_FAIL = -1;

// custom advice bar class
MyNotification MyNotification;

String filePathString; // absolute path to download file (including file name)

// notification bar jumps to Intent
Private Intent updateIntent = null;
Private PendingIntent updatePendingIntent = null;

DownFileThread DownFileThread; // custom file download thread

Private Handler updateHandler = new Handler(){
@ Override
Public void handleMessage(Message MSG) {
The switch (MSG. What) {
Case DOWNLOAD_COMPLETE:
// click to install PendingIntent
Uri Uri = Uri. FromFile (downFileThread getApkFile ());
Intent installIntent = new Intent(intent.action_view);
InstallIntent. SetDataAndType (uri, "application/VND. Android. Package - archive");
UpdatePendingIntent = PendingIntent. GetActivity (DownloadServices. This, 0, installIntent, 0).
MyNotification. ChangeContentIntent (updatePendingIntent);
MyNotification. Notification. Defaults = notification. DEFAULT_SOUND; // ring to remind
MyNotification. ChangeNotificationText (" the download is complete, please click on the install!" );

// stop service
/ / myNotification removeNotification ();
StopSelf ();
Break;
Case DOWNLOAD_FAIL:
// download failed
/ / myNotification changeProgressStatus (DOWNLOAD_FAIL);
MyNotification. ChangeNotificationText (file download failed! "" );
StopSelf ();
Break;
Default: // in download
The Log. I (" service ", "default" + MSG. What);
/ / myNotification changeNotificationText (MSG. What + "%");
MyNotification. ChangeProgressStatus (MSG. What);
}
}
};

Public DownloadServices () {
// TODO auto-generated constructor stub
/ / McOntext = context;
The Log i. (" service ", "DownloadServices1");

}

@ Override
Public void onCreate () {
// TODO auto-generated method stub
The Log i. (" service ", "onCreate");
Super. The onCreate ();
}

@ Override
Public void onDestroy () {
// TODO auto-generated method stub
The Log i. (" service ", "onDestroy");
If (downFileThread! = null)
DownFileThread. InteruptThread ();
StopSelf ();
Super. OnDestroy ();
}

@ Override
Public int onStartCommand(Intent Intent, int flags, int startId) {
// TODO auto-generated method stub
The Log i. (" service ", "onStartCommand");

UpdateIntent = new Intent(this, mainactivity.class);
PendingIntent updatePendingIntent = PendingIntent. GetActivity (updateIntent this, 0, 0).
MyNotification = new myNotification (this, updatePendingIntent, 1);

. / / myNotification. ShowDefaultNotification (R.d rawable ic_launcher, "test", "start download");
MyNotification. ShowCustomizeNotification (R.d rawable ic_launcher, download "test", R.l ayout. Notification);

FilePathString = Environment. External.getexternalstoragedirectory (.) getAbsolutePath () + "/ family. Apk";

// start a new thread download. If you use Service to download synchronously, it will cause ANR problems and the Service itself will block
DownFileThread = new downFileThread (updateHandler, "http://10.103.241.247:8013/update/download", filePathString);
New Thread (downFileThread.) start ();

Return super. OnStartCommand (intent, flags, startId);
}


@ Override
@ Deprecated
Public void onStart(Intent Intent, int startId) {
// TODO auto-generated method stub
The Log i. (" service ", "onStart");
Super. OnStart (intent, startId);
}

@ Override
Public IBinder onBind(Intent arg0) {
// TODO auto-generated method stub
The Log i. (" service ", "onBind");
Return null;
}

} 




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.