I want to install an apk file and set a broadcast-receiver in order to catch information concerning install status.
I have prepared a BroadcastReceiver class :
public class newPackageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("DEBUG"," test for application install/uninstall");
}
}
In the main activity, I first register a new receiver object, then instanciate button for application install.
public void onCreate(Bundle savedInstanceState) {
...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
filter.addAction(Intent.ACTION_PACKAGE_INSTALL);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
receiver = new newPackageReceiver();
registerReceiver(receiver, filter);
...
dlButton.setText(R.string.dl_button);
dlButton.setOnClickListener(new AppliDownloadOnClickListener(this ));
#Override
public void onDestroy(){
unregisterReceiver(receiver);
super.onDestroy();
}
In my OnclickListener class, i put :
#Override
public void onClick(View v) {
// actually, the below process is in an asyncTask
URL url;
Intent promptInstall;
try {
url = new URL(apkurl);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = Environment.getExternalStorageDirectory()+ "/download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file, "app.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();
promptInstall = new Intent(Intent.ACTION_VIEW);
promptInstall.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
if (promptInstall != null) {
activity.startActivity(promptInstall);
} else {
ErrorDetails.displayToastMessage(activity,R.string.connection_error);
}
} catch (...) {
...
}
}
With the above code (I have shrunk it), when button is clicked, installer is displayed and application is perfectly installed, but receiver class(newPackageReceiver) is never called. Registering (registerReceiver) is done in the onCreate method and unregisterReceiver is called in the onDestroy method, so it shoud be valid. Do you know why ?
Thank you for reading !
You need to add the data scheme to your intent filter.
filter.addDataScheme("package");
Also, ACTION_PACKAGE_INSTALL was never in use.
Related
I read all of the solutions about this problem.Also I know it can be considered as duplicated but it is not.
I see Error: Try Again toast message and I see Update Error log message.
I think at android v26 changed somethings about intent.setDataAndType or I dont know why this is not working.
Also I get the permissions something like this code
ActivityCompat.requestPermissions(Update.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
Problem can not be solved. I just want to do download and install apk file.
AndroidManifest.xml (I added write permission)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Update.java
package com.my.testapp;
public class Update extends AppCompatActivity {
ProgressDialog bar;
private static String TAG = "Update";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadNewVersion().execute();
}
class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
bar = new ProgressDialog(Update.this);
bar.setCancelable(false);
bar.setMessage("Downloading...");
bar.setIndeterminate(true);
bar.setCanceledOnTouchOutside(false);
bar.show();
}
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
bar.setIndeterminate(false);
bar.setMax(100);
bar.setProgress(progress[0]);
String msg = "";
if(progress[0]>99){
msg="Finishing... ";
}else {
msg="Downloading... "+progress[0]+"%";
}
bar.setMessage(msg);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
bar.dismiss();
if(result){
Toast.makeText(getApplicationContext(),"Update Done",
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"Error: Try Again",
Toast.LENGTH_SHORT).show();
}
}
#Override
protected Boolean doInBackground(String... arg0) {
Boolean flag = false;
try {
URL url = new URL("http://mydownloadurl.com/_download/update.apk");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = Environment.getExternalStorageDirectory()+"/Download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file,"app-debug.apk");
if(outputFile.exists()){
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
int total_size = 277962;//size of apk
byte[] buffer = new byte[1024];
int len1 = 0;
int per = 0;
int downloaded=0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
downloaded +=len1;
per = (int) (downloaded * 100 / total_size);
publishProgress(per);
}
fos.close();
is.close();
OpenNewVersion(PATH);
flag = true;
} catch (Exception e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
}
return flag;
}
}
void OpenNewVersion(String location) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Commonsware thanks a lot, I waste my 2-3 hours to do different ways.
Actually I added this code before but the problem was not solved.
I tried again and it worked, it might be lazy solution but it is working.
This url have more info about the problem ,other solutions can be applied,
but it is enough for me.
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
It is totally fixed thank you very much again.
Application also need this storage permission.
ActivityCompat.requestPermissions(Update.this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE
I am using the MuPDF library to display pdf in my app..
It is possible to view PDFs saved in internal or external memories but the App doesn't show the pdf if they are stored in assets folder of the app...
How to view in app PDFs?
I've seen solutions which say thatbwe can copy our in app PDFs in app associated folder and then use them later on...
but I can't get that..
here's the code -
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button showPDFBtn = (Button)findViewById(R.id.btn_show_pdf);
showPDFBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Uri uri = Uri.parse("file:///android_asset/test.pdf");
Intent intent = new Intent(MainActivity.this, MuPDFActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
}}
);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
}
Try below code
private void readAssetAndMakeCopy()
{
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(getFilesDir(), "git.pdf");
try
{
in = assetManager.open("git.pdf");
out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("file://" + getFilesDir() + "/git.pdf"),
"application/pdf");
startActivity(intent);
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
}
Make sure to include
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
in manifest
I have 10 to 12 Activity, All Activity has Help Menu as an Option Menu.
I am succeed with following code to create it and showing help on click of them.
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(cacheDir, "HELP.pdf")),"application/pdf");
context.startActivity(intent);
But I want to Reduce this code for all Activity, and for that i have created one class and make one method but still i want to reduce code.
I have searched and found that onClick attribute is available in OptionMenu but I didn't get how to use it.
Please Help..
Create a class, for example call it Helper, where you put a method called handleMenu(int id) and where you do all the work. Then, in every activity you call that method from onOptionsItemSelected(), passing the id of the item selected.
I have created following Class for openFile:
public class OpenHelpFile {
File cacheDir;
Context context;
/* Constructor */
public OpenHelpFile(Context context) {
this.context = context;
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "OOPS");
else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
try {
File helpFile = new File(cacheDir, "OOPS.pdf");
if (!helpFile.exists()) {
InputStream in = context.getAssets().open("OOPS.pdf");
OutputStream out = new FileOutputStream(helpFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.d(TAG, "File Copied...");
}
Log.d(TAG, "File exist...");
} catch (FileNotFoundException ex) {
Log.d(TAG, ex.getMessage() + " in the specified directory.");
System.exit(0);
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}
public void openHelpFile() {
/* OPEN PDF File in Viewer */
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(cacheDir, "OOPS.pdf")), "application/pdf");
context.startActivity(intent);
}
}
and I have call it from every OptionMenu like this:
new OpenHelpFile(context).openHelpFile();
I am downloading a file from ftp server. downloading code worked fine, however after download code screen doesn't show anything ,it gets black. Also download function is not returning true value, even the file is being saved in the specified directory.
public class FTPClass{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_player);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Intent intent = getIntent();
dirname = intent.getStringExtra("currentDirName");
MyFTPClient mftp = new MyFTPClient();
createPath = mftp.getAppRootPath().concat("/"+ dirname);
mftp.setCurrentDir(createPath);
System.out.println(mftp.ftpChangeDirectory(createPath));
FTPFile[] farr = mftp.ftpListAllFiles();
System.out.println(farr.length);
for(int i = 0; i<farr.length;i++){
System.out.println("SRC: "+createPath+"/"+farr[i].getName());
String src = createPath+"/"+farr[i].getName();
System.out.println("DEST: "+"/data/data/com.example.ftpplayer" + "/app_"+dirname);
String dest ="/data/data/com.example.ftpplayer" + "/app_"+dirname+"/"+farr[i].getName();
System.out.println(mftp.downloadFile(src,dest));
}
}
}
public class CallingIntent extends Activity{
System.out.println("In item click ");
Intent intent = new Intent(getApplicationContext(), FTPClass.class);
String dir = ((TextView) view).getText().toString();
intent.putExtra("currentDirName", dir);
startActivity(intent);
}
public class MyFTPClient{
public boolean downloadFile(String srcPath , String destPath){
try {
FileOutputStream fos = new FileOutputStream(destPath);
System.out.println(mftp.retrieveFile(srcPath, fos)); // retrieve file doesn't return true
fos.flush();
fos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
return false;
}
}
You need to run your code on the background thread, try using an asyncTask.
when user click on url link i want to install apk file from server.
please guide me how to do i searched on net i am not getting corresponding info
Thanks in advance
Aswan
Installing non-Market Apps on Android Phone
This is the code i use, it is not for a webview but you could easily override url loading and apply this code anyways..
The intent at the bottom is the answer to your question.
/**
* Main
* When started, will download latest version of AN APPLICATIONand launch an install
* Is just a dialog
*
* REQUIRES SDCARD
* #author Dag
*
*/
public class Main extends Activity {
ProgressDialog dlDialog;
String path = Environment.getExternalStorageDirectory()+ "/"; // Path to where you want to save the file
String inet = "http://www.google.com/test.apk"; // Internet path to the file
String cachedir = "";
String filename = "TMC.apk";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView webview = new TextView(this);
setContentView(webview);
File getcache = this.getCacheDir();
cachedir = getcache.getAbsolutePath();
dlDialog = new ProgressDialog(Main.this);
dlDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dlDialog.setTitle("Downloadin");
dlDialog.setMessage("Connecting");
dlDialog.show();
new Thread(new Runnable() {
public void run() {
String filePath = path;
InputStream is = null;
OutputStream os = null;
URLConnection URLConn = null;
try {
URL fileUrl;
byte[] buf;
int ByteRead = 0;
int ByteWritten = 0;
fileUrl = new URL(inet);
URLConn = fileUrl.openConnection();
is = URLConn.getInputStream();
String fileName = inet.substring(inet.lastIndexOf("/") + 1);
File f = new File(filePath);
f.mkdirs();
String abs = filePath + fileName;
f = new File(abs);
os = new BufferedOutputStream(new FileOutputStream(abs));
buf = new byte[1024];
/*
* This loop reads the bytes and updates a progressdialog
*/
while ((ByteRead = is.read(buf)) != -1) {
os.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
final int tmpWritten = ByteWritten;
runOnUiThread(new Runnable() {
public void run() {
dlDialog.setMessage(""+tmpWritten+" Bytes");
}
});
}
runOnUiThread(new Runnable() {
public void run() {
dlDialog.setTitle("Startar");
}
});
is.close();
os.flush();
os.close();
Thread.sleep(200);
dlDialog.dismiss();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(abs)),
"application/vnd.android.package-archive");
startActivity(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
You cannot force an APK to be installed...
If it were so anybody could hide viruses or spyware on some servers and when the user clicks a link it automatically gets installed...
Simply put the apk-file you want to install on your server and let the hyperlink point to it... just like to a zip-archive, movie or other executable file.
The browser simply will download the apk and install it (if the user wants so). The user of course needs to activate non-market apps in his settings... (as described in the link above)
I hope this helps you...