I am trying to download an apk file to update my application and apk is placed in ftp server and I am downloading that apk using FTP Client.
Even though I call mProgress.setProgress(percent);
the ProgressBar is not getting updated from the function where I download the apk file by ftp
public class UpdateAppByFTP extends AsyncTask<String,Void,Void> {
private Context context;
CopyStreamAdapter streamListener;
public void setContext(Context mContext){
context = mContext;
}
private ProgressDialog mProgress;
#Override
protected void onPreExecute(){
super.onPreExecute();
mProgress = new ProgressDialog(this.context);
mProgress.setMessage("Downloading new apk .. Please wait...");
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//mProgress.setIndeterminate(true);
mProgress.show();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
mProgress.dismiss(); //Dismiss the above Dialogue
}
#Override
protected Void doInBackground(String... arg0) {
try {
String serverName = arg0[0];
String userName = arg0[1];
String password = arg0[2];
String serverFilePath = arg0[3];
String localFilePath = arg0[4]; if(getFileByFTP(serverName,userName,password,serverFilePath,localFilePath)){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(localFilePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
context.startActivity(intent);
}else{
//Do nothing could not download
}
String apkLocation="/download/"+"SmartPOS.apk";
Intent intent1 = new Intent(Intent.ACTION_VIEW);
intent1.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() +apkLocation)), "application/vnd.android.package-archive");
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
context.startActivity(intent1);
} catch (Exception e) {
}
return null;
}
//Below code to download using FTP
public boolean getFileByFTP(String serverName, String userName,
String password, String serverFilePath, String localFilePath)
throws Exception {
FTPClient ftp = new FTPClient();
try {
ftp.connect(serverName);
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return false;
}
} catch (IOException e) {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException f) {
throw e;
}
}
throw e;
} catch (Exception e) {
throw e;
}
try {
if (!ftp.login(userName, password)) {
ftp.logout();
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
final int lenghtOfFile =(int)getFileSize(ftp,serverFilePath);
OutputStream output = new FileOutputStream(localFilePath);
CountingOutputStream cos = new CountingOutputStream(output) {
protected void beforeWrite(int n) {
super.beforeWrite(n);
int percent = Math.round((getCount() * 100) / lenghtOfFile);
Log.d("FTP_DOWNLOAD", "bytesTransferred /downloaded"+percent);
System.err.println("Downloaded "+getCount() + "/" + percent);
mProgress.setProgress(percent);
}
};
ftp.setBufferSize(2024*2048);//To increase the download speed
ftp.retrieveFile(serverFilePath, output);
output.close();
ftp.noop(); // check that control connection is working OK
ftp.logout();
return true;
}
catch (FTPConnectionClosedException e) {
Log.d("FTP_DOWNLOAD", "ERROR FTPConnectionClosedException:"+e.toString());
throw e;
} catch (IOException e) {
Log.d("FTP_DOWNLOAD", "ERROR IOException:"+e.toString());
throw e;
} catch (Exception e) {
Log.d("FTP_DOWNLOAD", "ERROR Exception:"+e.toString());
throw e;
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException f) {
throw f;
}
}
}
}
private static long getFileSize(FTPClient ftp, String filePath) throws Exception {
long fileSize = 0;
FTPFile[] files = ftp.listFiles(filePath);
if (files.length == 1 && files[0].isFile()) {
fileSize = files[0].getSize();
}
Log.d("FTP_DOWNLOAD", "File size = " + fileSize);
return fileSize;
}
}
Basically, the UI Does not get updated, also I am not sure whether the CountingOutputStream is the correct method to find the downloaded size of the file.
Thanks in advance.
I changed this retrieveFile section of the code and it is fine now
ftp.retrieveFile(serverFilePath, cos);
I tried your solution, it worked fine for me for file sizes up to 30 MB from FTP, going above, the download crashed every time. So I assumed the getCount() method as it is being called every time would result in some issue.
I even tried running the getCount() on separate thread, but still no use.
So finally I changed percent (for progress) variable to fraction of FileSize of local/FTP file size. So in above case it will be:
int percent = Math.round(output.length() * 100) / lenghtOfFile);
Works fine.
Related
An issue in auto-updating.That downloads a new app if an update is available and uninstall a current application and install a new app. It all works well till target SDK 22. but After target SDK 24 or updating Phone os above API Level 2 this functionality not working Whenever I install it shows package parsing error. because of an old app is already there and we are trying to install a new app.
targetSDK:24
compileSDK:28
minSDK:19
Here is a piece of code:
public class UpdateActivity extends AppCompatActivity implements AppConstants {
public static final String TAG = UpdateActivity.class.getSimpleName();
private String appName = "XYZ.apk";
private final Handler mHideHandler = new Handler();
private View mContentView;
private TextView txtDownloading;
private NumberProgressBar numberProgressBar;
private String updateUrl = "";
private final Runnable mHidePart2Runnable = new Runnable() {
#SuppressLint("InlinedApi")
#Override
public void run() {
// Delayed removal of status and navigation bar
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update);
updateUrl = getIntent().getStringExtra("url");
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
mContentView = findViewById(R.id.fullscreen_content);
mHideHandler.post(mHidePart2Runnable);
numberProgressBar = (NumberProgressBar) findViewById(R.id.numberbar8);
txtDownloading = (TextView) findViewById(R.id.txtDownload);
try {
new DownloadFileFromURL().execute();
} catch (Exception e) {
e.printStackTrace();
}
}
private class DownloadFileFromURL extends AsyncTask<String, Integer, String> {
DownloadFileFromURL() {
}
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... f_url) {
try {
HttpURLConnection c = (HttpURLConnection) new URL(updateUrl).openConnection();
c.setRequestMethod("POST");
c.setDoOutput(false);
c.connect();
int lengthOfFile = c.getContentLength();
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/");
file.mkdirs();
File outputFile = new File(file, appName);
if (outputFile.exists()) {
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] data = new byte[AccessibilityNodeInfoCompat.ACTION_NEXT_HTML_ELEMENT];
long total1 = 0;
while (true) {
int count = is.read(data);
if (count == -1) {
break;
}
total1 += (long) count;
Integer[] strArr = new Integer[1];
strArr[0] = DOWNLOAD_COUNT + ((int) ((100 * total1) / ((long) lengthOfFile)));
publishProgress(strArr);
fos.write(data, 0, count);
}
fos.close();
is.close();
installApp();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
protected void onProgressUpdate(Integer... progress) {
try {
numberProgressBar.setUnreachedBarColor(Color.parseColor("#CCCCCC"));
numberProgressBar.setProgressTextSize(30.0f);
if (progress[0] > 0 && progress[0] <= 20) {
numberProgressBar.setProgressTextColor(Color.parseColor("#E74C3C"));
numberProgressBar.setReachedBarColor(Color.parseColor("#E74C3C"));
txtDownloading.setTextColor(Color.parseColor("#E74C3C"));
}
if (progress[0] > 20 && progress[0] <= 40) {
numberProgressBar.setProgressTextColor(Color.parseColor("#FF3D7F"));
numberProgressBar.setReachedBarColor(Color.parseColor("#FF3D7F"));
txtDownloading.setTextColor(Color.parseColor("#FF3D7F"));
}
if (progress[0] > 40 && progress[0] <= 60) {
numberProgressBar.setProgressTextColor(Color.parseColor("#FFC73B"));
numberProgressBar.setReachedBarColor(Color.parseColor("#FFC73B"));
txtDownloading.setTextColor(Color.parseColor("#FFC73B"));
}
if (progress[0] > 60 && progress[0] <= 80) {
numberProgressBar.setProgressTextColor(Color.parseColor("#6DBCDB"));
numberProgressBar.setReachedBarColor(Color.parseColor("#6DBCDB"));
txtDownloading.setTextColor(Color.parseColor("#6DBCDB"));
}
if (progress[0] > 80 && progress[0] <= 100) {
numberProgressBar.setProgressTextColor(Color.parseColor("#70A800"));
numberProgressBar.setReachedBarColor(Color.parseColor("#70A800"));
txtDownloading.setTextColor(Color.parseColor("#70A800"));
}
numberProgressBar.setProgress(progress[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void onPostExecute(String file_url) {
numberProgressBar.setVisibility(View.GONE);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
private void installApp() {
try {
File apkFile = new File(Environment.getExternalStorageDirectory().getPath() + "/Download/", appName);
Intent intent = new Intent("android.intent.action.VIEW");
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I faced the same issue, and resolved it using the following:
Disabling Google Play Protect from playstore app worked the trick, i-e it was blocking the installation from external sources and i was able to get rid of the parse error.
On Android N and above, to give access to particular file or folder to make them accessible for other apps, you cant use File Uri, instead you have to use Provider Uri from FileProvider class , otherwise we get the FileUriExposedException such as android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData() etc.
For more information to how to setup FileProvider, see this guide:
https://developer.android.com/reference/android/support/v4/content/FileProvider
Hope this helps.
When apps installed, copy database work just fine. But when i tried to copy database in onUpgrade. the apps crashed even i left it empty in onPostExecute. But the database successfully copied and apps work just fine. Please help me.
LoginActivity
public class AsyncCopyDatabase extends AsyncTask<String, String, String> {
DatabaseHelper db;
ProgressDialog progress;
protected void onPreExecute(){
super.onPreExecute();
db = new DatabaseHelper(LoginActivity.this);
progress = new ProgressDialog(LoginActivity.this);
progress.setMessage("Preparing data. Please wait..");
progress.setCancelable(false);
progress.show();
}
#Override
protected String doInBackground(String... strings) {
//return null;
try {
db.createDatabase();
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
db.openDataBase();
return null;
}
#Override
protected void onPostExecute(String result) {
//Toast.makeText(LoginActivity.this, result, Toast.LENGTH_SHORT).show();
progress.dismiss();
}
}
DatabaseHelper
public void CopyDataBaseFromAsset() throws IOException{
InputStream in = ctx.getAssets().open(DATABASE_NAME);
Log.e("sample", "Starting copying" );
String outputFileName = DATABASE_PATH+DATABASE_NAME;
File databaseFile = new File(DATABASE_PATH);
// check if databases folder exists, if not create one and its subfolders
if (!databaseFile.exists()){
databaseFile.mkdir();
}
OutputStream out = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer))>0){
out.write(buffer,0,length);
}
Log.e("sample", "Completed" );
//db_delete();
out.flush();
out.close();
in.close();
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
if (newVersion > oldVersion) {
db.close();
boolean b = ctx.deleteDatabase(DATABASE_NAME);
if(b){
try{
CopyDataBaseFromAsset();
}
catch (IOException e){
throw new Error("Error copying database");
}
}
}
}
Please help me to add update code to my app to be update from my server thank you
nothing worked from net , i need complete guide
You can't install your app without users permission and root access but you can download your applications new version from server then ask users for install. Here is an example:
{
PackageManager manager = context.getPackageManager();
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
version = info.versionName;
if (newversion.replace(".", "") < version.replace(".", "")) {
new DownloadFileFromURL().execute("http://exampl.com/Content/files/example.apk");
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
private class DownloadFileFromURL extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = onCreateDialog();
}
#Override
protected String doInBackground(String... f_url) {
int count;
try {
File file = new File(Environment.getExternalStorageDirectory() + "/example.apk");
if (file.exists()) {
file.delete();
}
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
pDialog.setMax(lenghtOfFile / 1024);
InputStream input = new BufferedInputStream(url.openStream(), 8192);
OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/example.apk");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(total / 1024 + "");
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception ignored) {
}
return null;
}
protected void onProgressUpdate(String... progress) {
pDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String file_url) {
dialog.dismiss();
File file = new File(Environment.getExternalStorageDirectory() + "/example.apk");
if (file.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
//finish() or whatever you want
}
}
}
I'm using Apache's FTPClient to upload files to my server (images from the gallery if it matters)
I'm having a small and pretty insignificant problem, but I would still like to solve it.
The problem is that the bar is filled and reaches 100% before the upload actually completes, causing the dialog to show 100% for an extra 2-3 seconds on small files (and could be a lot more on files weighing several MBs).
I'm guessing it's because of the conversion from long to int, but that's just a guess.
Here's the code:
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(UploadActivity.this);
dialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
uploadImage.cancel(true);
}
});
dialog.setMessage("Uploading...\nPlease Wait.");
dialog.setIndeterminate(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.setCancelable(false);
dialog.setMax((int)(file.length()/1024));
dialog.setProgressNumberFormat ("%1dKB/%2dKB");
dialog.show();
}
#Override
protected String doInBackground(Void... params) {
CopyStreamAdapter streamListener = new CopyStreamAdapter() {
#Override // THIS PART IS RESPONSIBLE FOR UPDATING THE PROGRESS
public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
int percent = (int) (totalBytesTransferred * 100 / file.length());
publishProgress(percent);
}
};
String name = null;
ftp.setCopyStreamListener(streamListener);
FileInputStream fis = null;
try {
String extension = "";
String fileName = file.getName();
int i = fileName.lastIndexOf('.');
int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
if (i > p) {
extension = fileName.substring(i + 1);
}
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyy-hhmmss-SSS");
name = String.format("File-%s.%s", sdf.format(new Date()), extension);
ftp.connect(FTP_SERVER);
ftp.enterLocalPassiveMode();
ftp.login(ftpUser, ftpPassword);
ftp.setFileType(FTP.BINARY_FILE_TYPE);
fis = new FileInputStream(file);
if (!ftp.storeFile(name, fis)) {
showToast("Failed uploading");
return null;
}
ftp.logout();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return name;
}
#Override
protected void onProgressUpdate(Integer... values) {
dialog.setProgress(values[0]);
}
Thanks!
I'm apologise for my english.
I use the following piece of code to download a file from ftp host to Tablet. When I use Wi-Fi everything works well. But when I try to download a file using the mobile Internet, the download stops, but not always, sometimes finishes normally. I've found that stop is always going on "retrieveFile" or "logout", the program comes to these commands and no going further, and simply stands, the icon of data transfer does not blink, stops occur randomly. I tried to use different mobile operators, but there is no difference. What could be the reason?
And another question, but It is not so important, I've not found how to get the file size, and used my decision, maybe there is another way to get the file size ?
private void downloadFile(final String url, final String Message, final String Message2, final Uri uri) {
final ProgressDialog progressDialog = new ProgressDialog(this);
new AsyncTask() {
private Exception m_error = null;
#Override
protected void onPreExecute() {
progressDialog.setMessage(Message);
progressDialog.setCancelable(true);
progressDialog.setMax(100);
progressDialog
.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
}
#Override
protected File doInBackground(String... params) {
FileOutputStream fos = null;
File file = null;
FTPClient client = null;
try{
client = new FTPClient();
client.connect(ftp_host,Integer.parseInt(ftp_port));
client.login(ftp_user, ftp_password);
client.enterLocalPassiveMode();
client.setFileType(FTP.BINARY_FILE_TYPE);
String stat = "";
if (url.equals("MobiTrade.apk")){
client.changeWorkingDirectory("/var/srv/home/user/mobitrade/update/");}
file = new File(Environment.getExternalStorageDirectory(),
"/MobiTrade/update/MobiTrade.apk");}
stat = client.getStatus("/var/srv/home/user/mobitrade/update/MobiTrade.apk");
else {
client.changeWorkingDirectory("/var/srv/home/user/mobitrade/"+number+"/out/");
file = new File(Environment.getExternalStorageDirectory(),
"/MobiTrade/in/"+url);
if (url.equals("message.csv")) file.delete();
stat = client.getStatus("/var/srv/home/user/mobitrade/"+number+"/out/"+url);
}
final Integer FileSize;
if (stat.length() >= 64) {
stat = stat.substring(49,64);
stat = stat.trim();
FileSize = Integer.parseInt(stat);
}
else {
FileSize = 0;
}
fos = new FileOutputStream(file);
CountingOutputStream cos = new CountingOutputStream(fos){
protected void beforeWrite(int n){
super.beforeWrite(n);
publishProgress(getCount(), FileSize);
}
};
if (url.equals("MobiTrade.apk")){
client.retrieveFile("/var/srv/home/user/mobitrade/update/MobiTrade.apk", cos);
}
else {
client.retrieveFile("/var/srv/home/user/mobitrade/"+number+"/out/"+url, cos);
}
if (url.equals("message.csv")){
client.deleteFile("/var/srv/home/user/mobitrade/"+number+"/out/"+url);
}
client.logout();
}
catch (Exception e){
e.printStackTrace();
}
finally{
try{
if (fos != null) fos.close();
if (client.isConnected()) {
client.disconnect();
}
}
catch (IOException e){
e.printStackTrace();
}
}
return file;
}
protected void onProgressUpdate(Integer... values) {
progressDialog
.setProgress((int) ((values[0] / (float) values[1]) * 100));
};
#Override
protected void onPostExecute(File result) {
if (m_error != null) {
m_error.printStackTrace();
return;
}
progressDialog.hide();
if (url.equals("settings.csv"))
ProcessSettings(url);
else if (url.equals("MobiTrade.apk"))
ProcessUpdate();
else
ProcessData(url, Message2, uri);
}
}.execute(url);
}
Any help would be appreciable.