I am trying to update my app from outside Google Play, but I have an error, I have looked at everything and I cannot find a solution.
With the following 3 methods I hope to do the AutoUpdate:
private final String FILE_NAME = "app-release.apk";
public void checkStoragePermission(){
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
} else {
updateApp();}
}
private void updateApp() {
Uri uri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", new File(this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + FILE_NAME));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 123: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
updateApp();
} else {
checkStoragePermission();
}
return;
}
}
}
My Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.jose.updateinapp">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
</application>
</manifest>
And the .xml for FileProvider
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="files_root"
path="Android/data/${applicationId}" />
<external-path
name="external_files"
path="." />
</paths>
The app that i'm attempting to install is the same but with versionCode 2 and versionName 2.0 instead of versionCode 1 and versionName 2.0
When executed this throws an error on the device: error parsing the package
Nothing comes out in the run console. And in the logcat the following errors appear:
E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri
content://com.jose.updateinapp.provider/external_files/Android/data/com.jose.updateinapp/files/Download/app-release.apk
from pid=16603, uid=10035 requires the provider be exported, or
grantUriPermission()
Error staging apk from content URI
java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri
content://com.jose.updateinapp.provider/external_files/Android/data/com.jose.updateinapp/files/Download/app-release.apk
from pid=16603, uid=10035 requires the provider be exported, or
grantUriPermission()
Any solution? Thank you!
Sorry,something missed in my head.
Try this:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="" />
<external-files-path
name="Download"
path="" />
</paths>
uri = FileProvider.getUriForFile(context,
"packgeName.provider",
new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "xxx.apk"));
intentInstall.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
just try it. it worked in my project..
private void updateApp() {
Uri uri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", new File(this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + FILE_NAME));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//setFlags change addFlags
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);
}
Related
I am trying to open pdf files in this code with a library barteksc
I save a link as a URI in database Then I fetch and open the link in a library barteksc
The code works fine, the problem is when I restart the phone the PDF file is not opened It appears that the error in
load pdf error
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{f6420b9 6172:com.azizlabiod.librarypdfpro/u0a218} (pid=6172, uid=10218) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
code java
final int KITKAT_VALUE =1002;
Intent intent;
intent = new Intent();
if (Build.VERSION.SDK_INT < 19){
intent.setAction(Intent.ACTION_GET_CONTENT);
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION );
intent.setType("application/pdf");
try {
startActivityForResult(intent, KITKAT_VALUE);
} catch (ActivityNotFoundException e) {
//alert user that file manager not working
Toast.makeText(getApplicationContext(), R.string.toast_pick_file_error, Toast.LENGTH_SHORT).show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
if (requestCode == 1002
&& resultCode == Activity.RESULT_OK) {
Uri uri ;
if (resultData != null) {
uri=resultData.getData();
String name= getFileName(uri);
db.insertRowAdmins(name,uri.toString(),R.drawable.book,23, db.getNameTableId().get(positionTab));
setNotify();
}
}
}
code manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.LibraryPDFPro"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ShowBook"
android:exported="false" />
<activity
android:name=".ShowDiatel"
android:exported="false" />
</application>
</manifest>
probleme
/PDFView: load pdf error
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{f6420b9 6172:com.azizlabiod.librarypdfpro/u0a218} (pid=6172, uid=10218) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
at android.os.Parcel.readException(Parcel.java:1599)
at android.os.Parcel.readException(Parcel.java:1552)
at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:3776)
at android.app.ActivityThread.acquireProvider(ActivityThread.java:5034)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2044)
at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517)
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1121)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:958)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:811)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:765)
at com.github.barteksc.pdfviewer.source.UriSource.createDocument(UriSource.java:37)
at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:53)
at com.github.barteksc.pdfviewer.DecodingAsyncTask.doInBackground(DecodingAsyncTask.java:27)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Remove:
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
And, in your onActivityResult(), if the request was for ACTION_OPEN_DOCUMENT, call takePersistableUriPermissions() on a ContentResolver. That's how you get durable access to the content, and without that you lose access after a short while.
I have an app developed in java whose function is to capture the location when the app is active, background, destroyed and when the phone restarts
I already managed to capture the location when the app is active, background and destroyed but I am trying to do it when the phone reboots and create the task to capture but it says that the task was configured well but it does not execute it every 1 minute
My Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.rutas">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Rutas"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyForegroundServices"></service>
<receiver android:name=".MyBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
My Receiver
public class MyBroadcastReceiver extends BroadcastReceiver {
GPSTracker gps;
Context alarmContext;
#Override
public void onReceive(Context context, Intent intent) {
Log.e("onReceive", " Init Receive" );
alarmContext = context;
gps = new GPSTracker(context);
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
Log.e("Location", "Lat: " + latitude + "\n Long: " + longitude);
if(intent.getAction() != null){
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Log.e("Boot Completed", "Boot Completed");
setAlarmOnBoot();
Intent serviceIntent = new Intent(context, MyForegroundServices.class);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
context.startForegroundService(serviceIntent);
}else{
context.startService(serviceIntent);
}
}
}
}
public void setAlarmOnBoot(){
Log.e("Alarm Boot", "Initialize task");
try{
AlarmManager alarm = (AlarmManager) alarmContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(alarmContext, MyBroadcastReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(alarmContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 1000*60*1, pIntent);
Log.e("Success", "Alarm has been configured successfully");
} catch (Exception ex){
Log.e("Failed Try Receiver", ex.getMessage());
}
}
}
I am testing the app on a samsung A13 with android 12
I have an xls file in my server which needs to be downloaded in my phone using an apps. I'm using Nokia 5 and Android 9 for testing. My compile sdk version is 29. When I clicked download button, it didn't do anything, and after waiting for a while, a "Download Unsuccessful" notification popped up.
This is my MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_STORAGE_CODE = 1000;
EditText editUrl;
Button btnDownload;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editUrl = findViewById(R.id.edit_url);
btnDownload = findViewById(R.id.btn_download);
btnDownload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
String [] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, PERMISSION_STORAGE_CODE);
}
else {
startDownloading();
}
}
else {
startDownloading();
}
}
});
}
private void startDownloading() {
String url = editUrl.getText().toString().trim();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setTitle("Download");
request.setDescription("Downloading file...");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, ""+System.currentTimeMillis());
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch(requestCode) {
case PERMISSION_STORAGE_CODE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
startDownloading();
else
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}
}
I added network_security_config.xml (domain is blurred for security reason)
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">moneytracker.mauini******.com</domain>
</domain-config>
</network-security-config>
and added it in manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.main.downloadtest">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:networkSecurityConfig="#xml/network_security_config"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
And lastly, the download url is something like this:
http://moneytracker.mauini******.com/uploads/asd.xls
The file is successfully downloaded when that URL is executed in browser.
Am I missing something? Those are all I can get, searching for days. Please help.
First, on your code request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, ""+System.currentTimeMillis());. After Environment.DIRECTORY_DOWNLOADS param, you should put correct file name on it. coolfilename.xxx. Or, get its Uri value and put the Uri.getLastPathSegment() as the second parameter. Second, try to put request.setMimeType(param).
I want to sync a txt file in android internal storage (or sdcard for that matter) and have it automatically sync to a txt in my dropbox. i've used dropbox api but don't have hold on on how to achieve this. help needed please.
Update:
Here's my function to get the txt content to LogCat for now:
public void getFromDbx(){
try {
mDbxAcctMgr.startLink((Activity)this, REQUEST_LINK_TO_DBX);
final String TEST_DATA = " Database does not exist yet";
final String TEST_FILE_NAME = "data.txt";
DbxPath testPath = new DbxPath(DbxPath.ROOT, TEST_FILE_NAME);
// Create DbxFileSystem for synchronized file access.
DbxFileSystem dbxFs = DbxFileSystem.forAccount(mDbxAcctMgr.getLinkedAccount());
// Print the contents of the root folder. This will block until we can
// sync metadata the first time.
//dont need this code -- ahmed
// Create a test file only if it doesn't already exist.
if (!dbxFs.exists(testPath)) {
DbxFile testFile = dbxFs.create(testPath);
try {
testFile.writeString(TEST_DATA);
} finally {
testFile.close();
}
}
// Read and print the contents of test file. Since we're not making
// any attempt to wait for the latest version, this may print an
// older cached version. Use getSyncStatus() and/or a listener to
// check for a new version.
if (dbxFs.isFile(testPath)) {
String resultData;
DbxFile testFile = dbxFs.open(testPath);
try {
resultData = testFile.readString();
} finally {
testFile.close();
}
Log.i("dbx",resultData);
} else if (dbxFs.isFolder(testPath)) {
}
} catch (IOException e) {
}
My OnCreate:
super.onCreate(savedInstanceState);
setContentView(R.layout.main_screen);
//connect dbx to account
mDbxAcctMgr = DbxAccountManager.getInstance(getApplicationContext(), appKey, appSecret);
//get data from ems_data.txt from dropbox account
getFromDbx();
My OnActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_LINK_TO_DBX) {
if (resultCode == Activity.RESULT_OK) {
getFromDbx();
} else {
Log.i("dbxems", "Link to Dropbox failed or was cancelled.");
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
My Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testdatabaseactivity"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.CALL_PHONE" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:debuggable="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.testdatabaseactivity.TestDatabaseActivity"
android:label="#string/app_name" >
<intent-filter>
</intent-filter>
</activity>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:label="your tests label"
android:targetPackage="com.example.testdatabaseactivity" />
<uses-library android:name="android.test.runner" />
<activity
android:name="com.example.testdatabaseactivity.MainScreenActivity"
android:label="#string/title_activity_main_screen" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.testdatabaseactivity.SearchByName"
android:label="#string/title_activity_search_by_name"
android:windowSoftInputMode="stateHidden" >
</activity>
<activity android:name="com.dropbox.sync.android.DbxAuthActivity" />
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask" >
<intent-filter>
<data android:scheme="db-KEY_HERE" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name="com.dropbox.sync.android.DbxSyncService"
android:enabled="true"
android:exported="false"
android:label="Dropbox Sync" />
</application>
</manifest>
EDIT: there is no error, the app shows the auth screen, I click allow and then nothing happens. I can press allow 10 times and nothing happens at all..
In getFromDbx, you call startLink, which brings up the UI to link an account. When that succeeds, your onActivityResult is executed, where you call getFromDbx, which calls startLink again. :-) Looks like an infinite loop to me.
I'm trying to create an application that automatically downloads an apk from a specific server and install it on the system. My code for the installation looks like the following, but does not work.
File f = new File("/mnt/sdcard/download/", "Demo.apk");
Log.i("Demo", "f "+f.getAbsoluteFile());
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(f), "application/vnd.android.package_archive");
intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
m_context.startActivity(intent);
Do i need to give any rights in Manifest.xml for installation? I know that question has been asked before, but none of the answers have helped me so far.
This what I do in my case,
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(path+"/<application_name>.apk")), "application/vnd.android.package-archive");
startActivity(intent);
And these are the permissions..
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Thanks for all help, made it work at last. I share my working code and working Manifest.xml.
package test.installer;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class InstallToolActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Demo", "onCreate");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://"+"/mnt/sdcard/HelloWorld.apk"), "application/vnd.android.package-archive");
intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Manifext.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.installer"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.RESTART_PACKAGES"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:label="#string/app_name"
android:name=".InstallToolActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
//Fredrik
i also do
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
and my install lookd like this
intent.setDataAndType(Uri.parse("file://"+path), "application/vnd.android.package-archive");
my path is a String, like your f
You need to do this
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(f), "application/vnd.android.package-archive");
In your code, you have mentioned "package_archive", it should be "package-archive".
You would need the following permissions.
<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
If your targetSdkVersion is equal or higher than 24, then you need to use FileProvider implementation for Android N and newer Android versions.
Here is the whole implementation:
// utility method
private void openAppInstaller(Context context, File toInstall) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", toInstall);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent)
} else {
Uri apkUri = Uri.fromFile(toInstall);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
Add provider FileProvider to AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
</application>
</manifest>
And create provider_paths.xml under xml resources.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
More info about FileProvider configuration you can read here and here.
All credits go to #just_user because my answer based on his reply.