I'm using this class to update my application programatically which works perfectly.
public static class UpdateApp extends AsyncTask < String, Void, Void > {
private Context context;
public void setContext(Context contextf) {
context = contextf;
}
#Override
protected Void doInBackground(String...arg0) {
try {
URL url = new URL(arg0[0]);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = "/mnt/sdcard/Download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file, "update.apk");
if (outputFile.exists()) {
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
String filename = "/mnt/sdcard/Download/update.apk";
File filez = new File(filename);
if (filez.exists()) {
try {
final String command = "pm install -r " + filez.getAbsolutePath();
Process proc = Runtime.getRuntime().exec(new String[] {
"su",
"-c",
command
});
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
//Log.e("UpdateAPP", "Update error! " + e.getMessage());
}
return null;
}
}
As you can see the class makes use of "pm install" command.
What I want to do is to run the updated app as soon as the installation is completed, so the user doesn't stay outside application. Is there any way I can achieve this through package manager or adb?
String cmd = "am start -n " + getApplicationContext().getPackageName() + "/." + getActivity().getClass().getSimpleName();
...
os.writeBytes("pm install -r " + filename + " && " + cmd);
...
Related
hi friends!,
I am just trying to download image from url to internal storage http://github.com/google/fonts/blob/master/apache/roboto/Roboto-Regular.ttf?raw=true. I have created directory.
try
{
File folder = new File(getFilesDir() + "/"+"SS");
if (!folder.exists())
{
folder.mkdir();
Log.i("Directory","Created");
}
//URL connection
URL url = new URL(fonturl);
HttpURLConnection c = (HttpURLConnection)
url.openConnection();
c.connect();
File apkStorage=new File(getFilesDir().getPath());
Log.i("ApkStorage",""+apkStorage);
outputFile=new File(apkStorage.getAbsolutePath() +"/");
if(!outputFile.exists())
{
try {
outputFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("FIle", "File Created");
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
}
catch (Exception e) {
e.printStackTrace();
outputFile = null;
Log.e("Error", "Download Error Exception " + e.getMessage());
}
}
It just creating file name what I specified download.jpg not downloading file from url to internal storage.
Error: not downloading font in my directory showing error like this Download Error Exception /data/user/0/sdk.nfnlabs.in.customfonts/files (Is a directory). It should be download directly to my directory like roboto.tff without giving filename.
You can use following function
public void downloadFile(Context context){
public long enqueue;
public DownloadManager dm;
dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse("http://github.com/google/fonts/blob/master/apache/roboto/Roboto-Regular.ttf?raw=true"));
File direct = new File(Environment.getExternalStorageDirectory()
+ "/SS");
if (!direct.exists()) {
direct.mkdirs();
}
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false).setTitle("Downloading...")
.setDescription("Please wait. File is downloading...")
.setDestinationInExternalPublicDir("/SS","Roboto-Regular.ttf")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
enqueue = dm.enqueue(request);
context.registerReceiver(receiver, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
Broadcast receiver class is used for know weather download completes or not.
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
File direct = new File(Environment.getExternalStorageDirectory()
+ "/SS");
Toast.makeText(context,"File saved at location : "+direct.getAbsolutePath(),Toast.LENGTH_SHORT).show();
context.unregisterReceiver(receiver);
Activity_Downloads.callDownloadWS(context);
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c
.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c
.getInt(columnIndex)) {
}
}
}
}
};
And don't forget to add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You can get filename from HttpUrlConnection like below
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.connect();
File apkStorage = new File(getFilesDir().getPath());
Log.i("ApkStorage",""+apkStorage);
String raw = c.getHeaderField("Content-Disposition");
// raw = "attachment; filename=Roboto-Regular.ttf"
String fileName;
if(raw != null && raw.indexOf("=") != -1) {
fileName = raw.split("=")[1]; //getting value after '='
} else {
// fall back to random generated file name?
fileName = "unknown_file";
}
outputFile = new File(apkStorage, fileName);
Hope it'll help.
I want to update my app through local server. I have placed my application on server and through this code i am doing the task of updating it
public class UpdateClass extends AsyncTask<String, String, String> {
ProgressDialog progressDialog;
int status = 0;
private Context context;
public void onPreExecute() {
progressDialog = new ProgressDialog(Update.this);
progressDialog.setMessage("Please Wait.......");
progressDialog.show();
}
#Override
protected String doInBackground(String... arg0) {
try {
URL url = new URL(arg0[0]);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
// String PATH = Environment.getExternalStorageDirectory() + "/Download/";
String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/";
System.out.println("path..........." + Environment.getExternalStorageDirectory());
File file = new File(dir);
file.mkdirs();
File outputFile = new File(file, "location.apk");
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() +
"/Download/" + "location.apk")), "application/vnd.android.package-archive");
System.out.println("path........dsffffffffffffffsdfffff..." + Environment.getExternalStorageDirectory());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (FileNotFoundException fnfe) {
status = 1;
// Toast.makeText(context, "App not Available", Toast.LENGTH_LONG).show();
Log.e("File", "FileNotFoundException! " + fnfe);
} catch (Exception e) {
// Toast.makeText(context, "App update", Toast.LENGTH_LONG).show();
Log.e("UpdateAPP", "Exception " + e);
}
return null;
}
public void onPostExecute(String unused) {
progressDialog.dismiss();
/* if (status == 1)
Toast.makeText(context, "App not Available", Toast.LENGTH_LONG).show();
}*/
}
}
the code works fine with "http://localhost/androidservices/location.apk"
but when i replace this url with my server address that is https://liveserver/androidservices/location.apk then i get file not found exception in my logcat and in mobile phone a file with same file name is downloaded which size is 0 kb. i can access the url through browser as the file is easily being downloaded when opened with browser(chrome,mozilla).
I found the solution for this query. IIS servers don't support post methods and the method this url was using was post since i had used
c.setRequestMethod("GET");
c.setDoOutput(true);
Although i was passing GET but the method used was post.I changed it to
URL url = new URL(arg0[0]);
HttpURLConnection c = (HttpURLConnectionurl.openConnection();
c.connect();
and removed setDoOutput(true) and thus the method changed to GET and program started to work smoothly.
I am creating an app for my client, one of his requirements is to download and install an external apk (size approx. 62mb) on the device. The devices will be rooted, so that's not a problem. But, while downloading the apk using AsyncTask, the progress bar resets to 0% after reaching 34% (exact 34% every time, even on different devices) and throws java.io.IOException: unexpected end of stream.
Here is the code I'm using :
public class InstallAPK extends AsyncTask<Void,Integer,Void> {
ProgressDialog progressDialog;
int status = 0;
private Context context;
public InstallAPK(Context context, ProgressDialog progress){
this.context = context;
this.progressDialog = progress;
}
public void onPreExecute() {
if(progressDialog!=null)
progressDialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
try {
URL url = new URL(context.getString(R.string.kodi_apk_link));
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
// getting file length
int lenghtOfFile = c.getContentLength();
Log.e("File length", ""+lenghtOfFile);
File outputFile = new File(context.getFilesDir(), context.getString(R.string.kodi_apk_name));
if(outputFile.exists()){
if(outputFile.length() != lenghtOfFile)
outputFile.delete();
else {
publishProgress(-1);
final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
+ context.getString(R.string.kodi_apk_name);
installApk(commands);
return null;
}
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
//i tried both, with and without buffered reader
BufferedInputStream bufferedInputStream = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len1 = 0, total=0;
if (lenghtOfFile != -1)
{
buffer = new byte[lenghtOfFile];
do {
len1 += bufferedInputStream.read(buffer, len1, lenghtOfFile-len1);
publishProgress((int)((len1*100)/lenghtOfFile));
} while (len1 < lenghtOfFile);
}
//I was using this code before, but it's not working too
/*while ((len1 = is.read(buffer)) != -1) {
total += len1;
publishProgress((int)((total*100)/lenghtOfFile));
fos.write(buffer, 0, len1);
}*/
fos.flush();
fos.close();
bufferedInputStream.close();
is.close();
//Log.e("Directory path", myDir.getAbsolutePath());
publishProgress(-1);
final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
+ context.getString(R.string.kodi_apk_name);
installApk(commands);
} catch (FileNotFoundException fnfe) {
status = 1;
Log.e("File", "FileNotFoundException! " + fnfe);
}
catch(Exception e)
{
Log.e("UpdateAPP", "Exception " + e);
}
return null;
}
protected void onProgressUpdate(Integer... progress) {
if(progress[0]!=-1) {
// setting progress percentage
progressDialog.setProgress(progress[0]);
} else {
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Installing Kodi...");
}
}
public void onPostExecute(Void unused) {
if(progressDialog!=null) {
progressDialog.dismiss();
}
if(status == 1)
Toast.makeText(context,"App Not Available",Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"Successfully installed the app",Toast.LENGTH_LONG).show();
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getString(R.string.kodi_apk_package));
if(LaunchIntent!=null)
context.startActivity(LaunchIntent);
else
Toast.makeText(context, "Error in installig Kodi, Try again.", Toast.LENGTH_LONG).show();
}
private void installApk(String commands) {
try {
Process p = Runtime.getRuntime().exec("su");
InputStream es = p.getErrorStream();
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes(commands + "\n");
os.writeBytes("exit\n");
os.flush();
int read;
byte[] buffer = new byte[4096];
String output = new String();
while ((read = es.read(buffer)) > 0) {
output += new String(buffer, 0, read);
}
Log.v("AutoUpdaterActivity", output.toString());
p.waitFor();
} catch (IOException e) {
Log.v("AutoUpdaterActivity", e.toString());
} catch (InterruptedException e) {
Log.v("AutoUpdaterActivity", e.toString());
}
}
}
I tried everything to make this code work. But, it didn't. Then I found an alternative to this. I tried IntentService to download the apk, and surprisingly it worked. I think AsyncTask might have some kind of limit for downloading. To download using IntentService I used this code. The answer is very informative. It also has some other alternatives for downloading.
You should add connection timeout for HttpURLConnection.
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
//set timeout to 5 seconds , set your time here
c.setConnectTimeout(5000);
c.connect();
Its work for me.I hope its work for you.
I'm trying to download an apk file then install it.
I have done it with an external storage directory but when I download the file in a Local directory I can't parse it.
Here is the code on OnCreate method
final DownloadTask downloadTask = new DownloadTask(this);
downloadTask.execute("http://file.appsapk.com/wp-content/uploads/apps-2/Gmail.apk","Gmail.apk");
DownloadTask is a class that extends from AsyncTask.
Here is the background task:
#Override
protected String doInBackground(String... sUrl) {
file_name=sUrl[1];
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if (isSDPresent) {
directory = new File(Environment.getExternalStorageDirectory()+File.separator+"app_directory");
}
else
{
directory = getFilesDir();
}
if (!directory.exists())
directory.mkdirs();
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
int fileLength = connection.getContentLength();
input = connection.getInputStream();
output = new FileOutputStream(directory+"/"+file_name);
byte[] buffer = new byte[1024];
long total = 0;
int count;
while ((count = input.read(buffer)) != -1) {
if (isCancelled()) {
input.close();
return null;
}
total += count;
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(buffer, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (input != null)
input.close();
if (output != null)
output.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
And this is the post execution method that runs after the first one done downloading the file:
#Override
protected void onPostExecute(String result) {
mWakeLock.release();
mProgressDialog.dismiss();
if (result != null)
{
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(context, "File downloaded", Toast.LENGTH_SHORT).show();
File file = new File(directory, file_name);
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
context.startActivity(promptInstall);
finish();
}
It runs perfectly with an external storage but it won't run with an external one. Why not?
Try to use openfileoutput() rather than OutputStream in saving your file in internal storage and allow it to be readable. http://developer.android.com/guide/topics/data/data-storage.html#filesInternal . The package error is mainly caused by the permission of internal storage.
It's because of android application can not read from another application file if it is written using PRIVATE mode.So you have to change the mode of the file. i have just modify else part of your onPostExecute() method below.
try {
String tempfile="xyzfile";
File file = new File(directory, file_name);
FileInputStream inStream = new FileInputStream(file);
FileOutputStream fos = context.openFileOutput(tempfile,
context.MODE_WORLD_WRITEABLE | context.MODE_WORLD_READABLE);
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = inStream.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
inStream.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(context.getFilesDir(), tempfile);
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(
Uri.fromFile(file), "application/vnd.android.package-archive");
context.startActivity(promptInstall);
This code is running an apkfile after download from webserver.
But..
When the apkfile runs, it prints this message.
-Parse error
"There is a problem parsing the package."
When i run apkfile after copy to device, it did not print message.
How can I solve this ?
p.s) starting method is skinDownload(filename).
String File_Name = "";
String File_extend = "";
String fileURL = "http://URL/";
String Save_Path = "/data/data/kr.appsol.util.calc.formcalc/themes";
DownloadThread dThread;
ProgressDialog downDialog = null;
private void skinDownload(String filename){
File_Name = filename + ".apk";
File_extend = "apk";
File dir = new File(Save_Path);
if (!dir.exists()) {
dir.mkdir();
}
if (new File(Save_Path + "/" + File_Name).exists() == false) {
downDialog = ProgressDialog.show(Activity_SkinList.this, "", getString(R.string.setting_skin_downloading));
downDialog.show();
dThread = new DownloadThread(fileURL + "/" + File_Name,
Save_Path + "/" + File_Name);
dThread.start();
} else {
showDownloadFile();
}
}
class DownloadThread extends Thread {
String ServerUrl;
String LocalPath;
DownloadThread(String serverPath, String localPath) {
ServerUrl = serverPath;
LocalPath = localPath;
}
#Override
public void run() {
URL imgurl;
int Read;
try {
imgurl = new URL(ServerUrl);
HttpURLConnection conn = (HttpURLConnection) imgurl
.openConnection();
int len = conn.getContentLength();
byte[] tmpByte = new byte[len];
InputStream is = conn.getInputStream();
File file = new File(LocalPath);
FileOutputStream fos = new FileOutputStream(file);
for (;;) {
Read = is.read(tmpByte);
if (Read <= 0) {
break;
}
fos.write(tmpByte, 0, Read);
}
is.close();
fos.close();
conn.disconnect();
} catch (MalformedURLException e) {
Log.e("ERROR1", e.getMessage());
} catch (IOException e) {
Log.e("ERROR2", e.getMessage());
e.printStackTrace();
}
mAfterDown.sendEmptyMessage(0);
}
}
Handler mAfterDown = new Handler() {
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
downDialog.dismiss();
// run
showDownloadFile();
}
};
private void showDownloadFile() {
File apkFile = new File(Save_Path + "/" + File_Name);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
startActivity(intent);
}
You probably need to flush the stream before closing it:
fos.flush();
fos.close();