How to correct update Android .apk? - android

Intent openIntent;
File file = new File(mApkPath);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String auth = mContext.getPackageName() + ".file.provider";
Uri apkUri = FileProvider.getUriForFile(mContext, auth, file);
openIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
openIntent.setData(apkUri);
openIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
openIntent = new Intent(Intent.ACTION_VIEW);
openIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
openIntent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
return openIntent;
I found this way can open an Activity which is mean "Install Success" in low SDK version Android device, but in hight SDK version, when install finished, the app will like crash, even if the new .apk was installed.
Have any way to open the activity which is mean "Install Success", so that let user can choose install 'Finished' or 'Open'?
By the way, I got resultCode == RESULT_CANCELED, actually, new .apk was installed. And I notice PackageInstaller can user update apk, but how to use it? I read ApiDemos but got result == PackageInstaller.STATUS_PENDING_USER_ACTION by int result = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE), but .apk was Installed and no any 'Finished' or 'Open' button.
Thanks!

Related

How to install Apk from app using Xamarin android

I am trying to update my app programmatically.
I am able to download the new version of the app apk.
But when the installation code runs nothing happens except an activity that is opened and then closed returning to my app
The installation code is
Java.IO.File apkFile = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/download/" + "com.tri.GOT.apk");
var context = Android.App.Application.Context;
var downloadUri = FileProvider.GetUriForFile(context, "com.tri.GOT.fileprovider", apkFile);
Intent install = new Intent(Intent.ActionView);
install.AddFlags(ActivityFlags.NewTask);
install.AddFlags(ActivityFlags.GrantReadUriPermission);
install.AddFlags(ActivityFlags.GrantWriteUriPermission);
install.AddFlags(ActivityFlags.GrantPersistableUriPermission);
install.SetDataAndType(downloadUri, "application/vnd.android.package-archive");
context.StartActivity(install);

Installation dialog not shown in oreo when done programatically if device is not rooted

I am trying to update app after showing the alert dialog in my app. It is working fine below Android Oreo. Here is what I have tried till now
String ANDROID_PACKAGE = "application/vnd.android.package-archive";
File update_apk = new File(context.getFilesDir(), intent.getStringExtra("update_file"));
Intent notificationIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
notificationIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
notificationIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
notificationIntent.setDataAndType(
FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", update_apk),
ANDROID_PACKAGE);
} else {
notificationIntent = new Intent(Intent.ACTION_VIEW);
notificationIntent.setDataAndType(
Uri.parse("file://" + update_apk.getAbsolutePath()),
ANDROID_PACKAGE);
}
startActivity(notificationIntent);
How to show this app update dialog in the devices which are not rooted. Any help would be appreciated. Thanks in aadvance.
Check below permission in your manifest.xml file.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Also check your file provider for Intent.VIEW_ACTION.
More reference check this page Android install apk with Intent.VIEW_ACTION not working with File provider
enjoy code.

In App Upgrade for Android Oreo (API Version 26)

My App is distributed outside of Play Store and it is upgraded within the App when there is a new version available. I am using the below code to start the install (after the file was downloaded using DownloadManager)
String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/app.apk";
For Android N (24):
Uri contentUri = FileProvider.getUriForFile(ctxt, BuildConfig.APPLICATION_ID + ".provider", new File(destination));
Intent openFileIntent = new Intent(Intent.ACTION_VIEW);
openFileIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
openFileIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
openFileIntent.setData(contentUri);
startActivity(openFileIntent);
For Android 23 and below:
final Uri uri = Uri.parse("file://" + destination);
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setDataAndType(uri,"application/vnd.android.package-archive");
startActivity(install);
When I use the same code for "Android N", it is not showing the system install activity in Android Oreo. Anyone who has solved this problem?

Android install apk with Intent.VIEW_ACTION not working with File provider

My app has an auto-update feature that download an APK and when the download is finished that a Intent.VIEW_ACTION to open the app and let the user install the downloaded apk
Uri uri = Uri.parse("file://" + destination);
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setDataAndType(uri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);
This works great for all the device < 24
Now with Android 24 apparently we are not allowed any more to start intents with file:/// and after some googling it was advised to use A File Provider
new code:
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri apkUri = FileProvider.getUriForFile(AutoUpdate.this,
BuildConfig.APPLICATION_ID + ".provider", file);
install.setDataAndType(apkUri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);
Now activity.startActivity(install); throws an error
No Activity found to handle Intent { act=android.intent.action.VIEW
dat=content://com.xxxx.xx.provider/MyFolder/Download/MyApkFile.apk
typ=application/vnd.android.package-archive flg=0x4000000 }
Is there any way I can open the APK viewer in Android 7 (24) ?
After a lot of trying I have been able to solve this by creating different Intents for anything lower than Nougat as using the FileProvider to create an install intent with Android Versions before Nougat causes the error:
ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.INSTALL_PACKAGE dat=content://XXX.apk flg=0x1 }
While using a normal Uri on Android Nougat creates the following error:
FileUriExposedException: file:///XXX.apk exposed beyond app through Intent.getData()
My solution which is working for me with Android N on the emulator and a phone running Android M.
File toInstall = new File(appDirectory, appName + ".apk");
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", toInstall);
intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
Uri apkUri = Uri.fromFile(toInstall);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
activity.startActivity(intent);
UPDATE FOR Android Nougat 7.1:
You also need to add the permission REQUEST_INSTALL_PACKAGES in your manifest. Its available from Api Level 23 (Android 6.0 Marshmallow) and required from Level 25 (Android 7.1 Nougat).
UPDATE:
Remember to request the permissions for read and write to external storage if the file you try to install is on the external storage. And also to set up a correct FileProvider for Android Nougat and above.
First check if you have write permission by calling canReadWriteExternal() below, if not call requestPermission() before:
private static final int REQUEST_WRITE_PERMISSION = 786;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
}
private boolean canReadWriteExternal() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}
Here is an example of a file provider for the Download folder on the external storage. AndroidManifest.xml:
<application ... >
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
</application>
resources/xml/filepaths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_download" path="Download"/>
</paths>
If you get an error while installing the .apk saying something like "There is a problem parsing the package." it could be that you haven't asked for the read/write permission or the file you try to install doesn't exist or is corrupt.
UPDATE FOR Android Oreo 8.0:
You have to check if current application is allowed to install the APK on Android Oreo 8.0 or above.
You can check if your app is allowed to install APK by using canRequestPackageInstalls method of PackageManager class. If it returns false, then you can launch intent with ACTION_MANAGE_UNKNOWN_APP_SOURCES action to launch settings dialog where user can allow the app to install APKs.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& !getPackageManager().canRequestPackageInstalls()) {
Intent unknownAppSourceIntent = new Intent()
.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
.setData(Uri.parse(String.format("package:%s", getPackageName())));
unknownAppSourceDialog.launch(unknownAppSourceIntent);
} else {
// App already have the permission to install so launch the APK installation.
startActivity(intent);
}
Make sure you add the following code to your activity to receive the result of intent.
ActivityResultLauncher<Intent> unknownAppSourceDialog = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// User has allowed app to install APKs
// so we can now launch APK installation.
startActivity(intent);
}
});
I had this problem when calling start activity.after pausing my current activity, it suddenly came back and called onResume. like nothing happened. my problem was with this permission in manifest:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
almost no one mentioned that. so remember this.
in sdk >= 24 you need to use provider because it needs an intent starting with file:///
below sdk 24 you should give uri starting with content:///
so that's why we need file provider for sdk 24 and above. I don't think I need to write any codes for this as #just_user has written correct answer.
https://stacklearn.ir
This could be the problem, you have
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
in your example it should be
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
as install is the name of the intent.
You should note that for API < 24 you need to use:
setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
instead of setting data and type separately:
data = Uri.fromFile(apkFile)
type = "application/vnd.android.package-archive"
otherwise, you will get ActivityNotFoundException
For all of those who face the issue "There was a problem parsing this package.".
Set manualy the premissions.
ContextCompat.checkSelfPermission(getApplicationContext(), READ_EXTERNAL_STORAGE);
See this exemple :
Download And Install App Programmatically

Android: How to open a specific folder via Intent and show its content in a file browser?

I thought this would be easy but as it turns out unfortunately it's not.
What I have:
I have a folder called "myFolder" on my external storage (not sd card because it's a Nexus 4, but that should not be the problem). The folder contains some *.csv files.
What I want:
I want to write a method which does the following: Show a variety of apps (file browsers) from which I can pick one (see picture). After I click on it, the selected file browser should start and show me the content of "myFolder". No more no less.
My question:
How exactly do I do that? I think I came quite close with the following code, but no matter what I do - and I'm certain that there must be something I didn't get right yet - it always opens only the main folder from the external storage.
public void openFolder()
{
File file = new File(Environment.getExternalStorageDirectory(),
"myFolder");
Log.d("path", file.toString());
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setDataAndType(Uri.fromFile(file), "*/*");
startActivity(intent);
}
This should help you:
Uri selectedUri = Uri.parse(Environment.getExternalStorageDirectory() + "/myFolder/");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(selectedUri, "resource/folder");
if (intent.resolveActivityInfo(getPackageManager(), 0) != null)
{
startActivity(intent);
}
else
{
// if you reach this place, it means there is no any file
// explorer app installed on your device
}
Please, be sure that you have any file explorer app installed on your device.
EDIT: added a shantanu's recommendation from the comment.
LIBRARIES:
You can also have a look at the following libraries https://android-arsenal.com/tag/35 if the current solution doesn't help you.
I finally got it working. This way only a few apps are shown by the chooser (Google Drive, Dropbox, Root Explorer, and Solid Explorer). It's working fine with the two explorers but not with Google Drive and Dropbox (I guess because they cannot access the external storage). The other MIME type like "*/*" is also possible.
public void openFolder(){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()
+ File.separator + "myFolder" + File.separator);
intent.setDataAndType(uri, "text/csv");
startActivity(Intent.createChooser(intent, "Open folder"));
}
Here is my answer
private fun openFolder() {
val location = "/storage/emulated/0/Download/";
val intent = Intent(Intent.ACTION_VIEW)
val myDir: Uri = FileProvider.getUriForFile(context, context.applicationContext.packageName + ".provider", File(location))
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
intent.setDataAndType(myDir, DocumentsContract.Document.MIME_TYPE_DIR)
else intent.setDataAndType(myDir, "*/*")
if (intent.resolveActivityInfo(context.packageManager, 0) != null)
{
context.startActivity(intent)
}
else
{
// if you reach this place, it means there is no any file
// explorer app installed on your device
CustomToast.toastIt(context,context.getString(R.string.there_is_no_file_explorer_app_present_text))
}
}
Here why I used FileProvider - android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
I tested on this device
Devices: Samsung SM-G950F (dreamltexx), Os API Level: 28
Intent chooser = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(Environment.getDownloadCacheDirectory().getPath().toString());
chooser.addCategory(Intent.CATEGORY_OPENABLE);
chooser.setDataAndType(uri, "*/*");
// startActivity(chooser);
try {
startActivityForResult(chooser, SELECT_FILE);
}
catch (android.content.ActivityNotFoundException ex)
{
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
In code above, if setDataAndType is "*/*" a builtin file browser is opened to pick any file, if I set "text/plain" Dropbox is opened. I have Dropbox, Google Drive installed. If I uninstall Dropbox only "*/*" works to open file browser. This is Android 4.4.2. I can download contents from Dropbox and for Google Drive, by getContentResolver().openInputStream(data.getData()).
Thread is old but I needed this kind of feature in my application and I found a way to do it so I decided to post it if it can help anyone in my situation.
As our device fleet is composed only by Samsung Galaxy Tab 2, I just had to find the file explorer's package name, give the right path and I succeed open my file explorer where I wanted to. I wish I could use Intent.CATEGORY_APP_FILES but it is only available in API 29.
Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.sec.android.app.myfiles");
Uri uri = Uri.parse(rootPath);
if (intent != null) {
intent.setData(uri);
startActivity(intent);
}
As I said, it was easy for me because our clients have the same device but it may help others to find a workaround for their own situation.
this code will work with OI File Manager :
File root = new File(Environment.getExternalStorageDirectory().getPath()
+ "/myFolder/");
Uri uri = Uri.fromFile(root);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(uri);
startActivityForResult(intent, 1);
you can get OI File manager here : http://www.openintents.org/en/filemanager
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, DocumentsContract.Document.MIME_TYPE_DIR);
startActivity(intent);
Will open files app home screen
Today, you should be representing a folder using its content: URI as obtained from the Storage Access Framework, and opening it should be as simple as:
Intent i = new Intent(Intent.ACTION_VIEW, uri);
startActivity(i);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/csv");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), 0);
} catch (android.content.ActivityNotFoundException ex) {
ex.printStackTrace();
}
then you just need to add the response
public void onActivityResult(int requestCode, int resultCode, Intent data){
switch (requestCode) {
case 0: {
//what you want to do
//file = new File(uri.getPath());
}
}
}
You seem close.
I would try to set the URI like this :
String folderPath = Environment.getExternalStorageDirectory()+"/pathTo/folder";
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
Uri myUri = Uri.parse(folderPath);
intent.setDataAndType(myUri , "file/*");
startActivity(intent);
But it's not so different from what you have tried.
Tell us if it changes anything ?
Also make sure the targeted folder exists, and have a look on the resulting Uri object before to send it to the intent, it may not be what we are expected.
File temp = File.createTempFile("preview", ".png" );
String fullfileName= temp.getAbsolutePath();
final String fileName = Uri.parse(fullfileName)
.getLastPathSegment();
final String filePath = fullfileName.
substring(0,fullfileName.lastIndexOf(File.separator));
Log.d("filePath", "filePath: " + filePath);
fullfileName:
/mnt/sdcard/Download_Manager_Farsi/preview.png
filePath:
/mnt/sdcard/Download_Manager_Farsi

Categories

Resources