Permission Denial: opening provider android.support.v4.content.FileProvider - java

I was having some problem when trying to perform an application upgrade in Android emulator. The flow of the scenario is from an Activity, I will execute AsyncTask A which open up fragment A, then inside AsyncTask A, I will check if version upgrade is available.
If available and user selected "Okay" from fragment A, I will proceed to AsyncTask B to open up fragment B which show a message to user saying that upgrading is in process. In AsyncTask B doInBackground(), I will execute the install() and in onPostExecute(), I will show successful message.
In my AsyncTask B where I execute the install:
#Override
protected Boolean doInBackground(Void... params) {
boolean ret= viewmodel.installApk(mActivity);
return ret;
}
In my view model class:
public boolean installApk(Activity mActivity){
boolean success = false;
String fullPath = scanDirectoryForApk();
System.out.println("INSTALLING APK ......................... ");
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri apkURI = FileProvider.getUriForFile(mActivity, mActivity.getApplicationContext().getPackageName() + ".provider", new File(fullPath));
intent.setDataAndType(apkURI, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(intent);
return true;
}
However, when I execute the code above, no error message was shown and the version upgrade is not working as well. It basically just restart the intent and there is no upgrade at all.
It does not prompt me for the permission to install new version as well. Any ideas?
By the way, my android emulator is not rooted and therefore I could not use the "su" command approach.
Thanks!
EDIT
As suggestion by #Sagar, I changed my code above to:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri apkURI = FileProvider.getUriForFile(mActivity, mActivity.getApplicationContext().getPackageName() + ".provider", new File(fullPath));
List<ResolveInfo> resInfoList = mActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
mActivity.grantUriPermission(packageName, apkURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setDataAndType(apkURI, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(intent);
And I am getting new error message from logcat:
Error staging apk from content URI
java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{3883c8 9647:com.google.android.packageinstaller/u0a20} (pid=9647, uid=10020) that is not exported from UID 10085
The intent error message is telling me "There was a problem parsing package".

You can try to merge
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
into
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK);
I met the same issue as you, and this solution rescued myself.

Related

Error while adding Galaxy Store review broadcast

I publish my apps and games on Galaxy Store some apps are here in this LINK
Using official (document)[https://developer.samsung.com/galaxy-store/customer-review/galaxy-store-review-broadcast.html] provided by Galaxy Store Developers I tried making a broadcaste of Rate this app in OnCreate inside MainActivity.java
Code I used in OnCreate:
ApplicationInfo ai =
getPackageManager().getApplicationInfo("com.sec.android.app.samsungapps",
PackageManager.GET_META_DATA);
int inappReviewVersion = ai.metaData.getInt("com.sec.android.app.samsungapps.review.inappReview", 0);
if (inappReviewVersion > 0){
// if inappReviewVersion is larger than zero, Galaxy Store supports in-app review function
} else {
// else, Galaxy Store does not support in-app review function
}
// 1. Check your review authority by Galaxy Store package
Intent intent = new Intent("com.sec.android.app.samsungapps.REQUEST_INAPP_REVIEW_AUTHORITY");
intent.setPackage("com.sec.android.app.samsungapps");
intent.putExtra("callerPackage", com.protecgames.htmleditor); // targetPacakge : your package name
sendBroadcast(intent);
// 2. Get result of authority checking from Galaxy Store package
IntentFilter filter = new IntentFilter();
filter.addAction("com.sec.android.app.samsungapps.RESPONSE_INAPP_REVIEW_AUTHORITY");
authorityReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// If true, you have authority to write review
boolean hasAuthority = intent.getBooleanExtra("hasAuthority", false);
// By using deeplinkUrlForReview, you can open review activity of Galaxy Store
String deeplinkUri = intent.getStringExtra("deeplinkUri");
}
}
Intent intent = new Intent();
intent.setData(Uri.parse(deeplinkUri)); // deeplinkUri, included in response intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
startActivity(intent);
The error while executing project:
----------
1. ERROR in /storage/emulated/0/.sketchware/mysc/601/app/src/main/java/com/my/newproject/MainActivity.java (at line 44)
ApplicationInfo ai = getPackageManager().getApplicationInfo("com.sec.android.app.samsungapps", PackageManager.GET_META_DATA); int inappReviewVersion = ai.metaData.getInt("com.sec.android.app.samsungapps.review.inappReview", 0); if (inappReviewVersion > 0){ // if inappReviewVersion is larger than zero, Galaxy Store supports in-app review function } else { // else, Galaxy Store does not support in-app review function } // 1. Check your review authority by Galaxy Store package Intent intent = new Intent("com.sec.android.app.samsungapps.REQUEST_INAPP_REVIEW_AUTHORITY"); intent.setPackage("com.sec.android.app.samsungapps"); intent.putExtra("callerPackage", com.protecgames.htmleditor); // targetPacakge : your package name sendBroadcast(intent); // 2. Get result of authority checking from Galaxy Store package IntentFilter filter = new IntentFilter(); filter.addAction("com.sec.android.app.samsungapps.RESPONSE_INAPP_REVIEW_AUTHORITY"); authorityReceiver = new BroadcastReceiver() { #Override public void onReceive(Context context, Intent intent) { // If true, you have authority to write review boolean hasAuthority = intent.getBooleanExtra("hasAuthority", false); // By using deeplinkUrlForReview, you can open review activity of Galaxy Store String deeplinkUri = intent.getStringExtra("deeplinkUri"); } } Intent intent = new Intent(); intent.setData(Uri.parse(deeplinkUri)); // deeplinkUri, included in response intent intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_INCLUDE_STOPPED_PACKAGES); startActivity(intent);
^
Syntax error, insert "}" to complete Statement
----------
1 problem (1 error)
I am using Sketchware v6.4.0 Beta 6 with add Source Directly block

Launch Telegram app from Android application with message and recipient

I need to open Telegram from my own Android App prepopulating both the message and recipient (and not having to choose betwenn Chrome or Telegram),
I achieved the first one with this code:
final String appName = "org.telegram.messenger";
Intent tIntent = new Intent(Intent.ACTION_SEND);
tIntent.setType("text/plain");
tIntent.setPackage(appName);
tIntent.putExtra(Intent.EXTRA_TEXT, msg);
mUIActivity.startActivity(tIntent);
And the second one with this code:
Intent tIntent = new Intent(Intent.ACTION_VIEW);
tIntent.setData(Uri.parse("http://telegram.me/USERID"));
startActivity(tIntent);
(I removed all checks like isTelegramInstalled for simplicity)
I tried to mix the two methods
adding some intent extra such as msg we get to this code that will open Telegram, in one click, with pre-populated message and recipient:
Intent telegramIntent = new Intent(Intent.ACTION_SEND);
tIntent.setDataAndType(Uri.parse("http://telegram.me/username"), "text/plain");
final String appName = "org.telegram.messenger";
tIntent.setPackage(appName);
tIntent.putExtra(Intent.EXTRA_TEXT, "hello");
startActivity(tIntent);
...aaand it didn't work!
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND dat=http://telegram.me/... flg=0x1 pkg=org.telegram.messenger clip={null T:hello} (has extras) }
Any idea how to achieve this?
Please try below function for open Telegram
public static void openTelegram(Activity activity, String userName) {
Intent general = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.com/" + userName));
HashSet<String> generalResolvers = new HashSet<>();
List<ResolveInfo> generalResolveInfo = activity.getPackageManager().queryIntentActivities(general, 0);
for (ResolveInfo info : generalResolveInfo) {
if (info.activityInfo.packageName != null) {
generalResolvers.add(info.activityInfo.packageName);
}
}
Intent telegram = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/" + userName));
int goodResolver = 0;
// gets the list of intents that can be loaded.
List<ResolveInfo> resInfo = activity.getPackageManager().queryIntentActivities(telegram, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
goodResolver++;
telegram.setPackage(info.activityInfo.packageName);
}
}
}
//TODO: if there are several good resolvers create custom chooser
if (goodResolver != 1) {
telegram.setPackage(null);
}
if (telegram.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivity(telegram);
}
}
I hope this can help You!
Thank You.
In your case
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND dat=http://telegram.me/... flg=0x1 pkg=org.telegram.messenger clip={null T:hello} (has extras) }
Telegram chat activity class has a different name and you pass other activity name.
Find which class use telegram for chat activity and pass it on set package method

Starting react-native activity from java module (android)

I see that you can bring your activity form the background to the foreground in android using the following lines
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Now the problem is I don't know how to get the name of the react activity to work - When I try to compile I get
error: cannot find symbol Intent i = new Intent(mReactContext,
MainActivity.class);
symbol: class MainActivity
I'm not very experienced with java - so this is part of my problem, I tried using getCurrentActivity() - but this doesn't seem to work either.
Anyone has an idea?
Thanks!
If you have access to reactContext (I see you have) you can try this:
Context context = getReactApplicationContext();
String pn = context.getApplicationContext().getPackageName();
Intent li = context.getPackageManager().getLaunchIntentForPackage(pn);
context.startActivity(li);
String pn is just a package name (e.g. "com.yourapp"), so you can skip getPackageName() and just pass your package name to getLaunchIntentForPackager(). You can check this solution on react-native-system-notification
You should get reference of your first activity. Then Create your intent and start activity. Run the code below somewhere in your code(for example in a react method which triggers an activity)
Activity currentActivity = getCurrentActivity();
Intent intent = new Intent(name of your activity);
currentActivity.startActivityForResult(intent,FLAG_ACTIVITY_NEW_TASK
);
// create onActivityResult method to process your task according to result
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FLAG_ACTIVITY_NEW_TASK ) {
// do your job
}
}
It seems you use MainActivity.class as parameter in intent. I'm not an expert but it seems wrong. In a react-native project mainactivity will be triggered automatically and index.android.js will be called. You can use an activity you create as well you don't have to use native android activities like Intent.ACTION_GET_CONTENT which can be used to get information of an image from gallery.

How can I make an apk auto install when download completes

Hi guys was wondering if there was a bit of code I could use that would make an app auto install once the download completes?
My app has a download section with in it. I was using Google Drive to handle the downloads. but I am encountering issues with some devices. So I have decided to move away from google
I am now using media fire as my host. My app uses direct download. But it always downloads using the download manager. What I would like it to do is more like how Google Drive works with direct download. Which is it gives me the option to install as soon as download completes.which i have now solved with these few lines of code
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new
File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
is there a way to check download folder before downloading the file. if the file is already there install if not got to web page for download. rather it saying parse error then going to webpage or having multiple downloads of same file.
Thanks in advance as always.
You can get the downloaded Uri after the download complete, so you don't have to specify a file name to save. If you use DownloadManager, below is a simple example.
final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://remotehost/your.apk"));
final long id = downloadManager.enqueue(request);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
Intent installIntent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
installIntent.setDataAndType(downloadManager.getUriForDownloadedFile(id),
"application/vnd.android.package-archive");
} else {
Cursor cursor = downloadManager.query(new DownloadManager.Query().setFilterById(id));
try {
if (cursor != null && cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
String localUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
installIntent.setDataAndType(Uri.parse(localUri), "application/vnd.android.package-archive");
}
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.sendBroadcast(installIntent);
}
}
};
registerReceiver(broadcastReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

Make a call in android that does not have an activity

I made an android app to call to a number when a message is received using broadcast receiver.
But I am getting an error no activity found to handle the intent. How can I solve this problem?
Code is given below
Intent intent1 = new Intent(Intent.ACTION_CALL);
intent1.setData(Uri.parse(incno1));
context.startActivity(intent1);
I added the line intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);, but this also does not solve my problem.
The protocol is incorrect. You need to do the following:
callIntent.setData(Uri.parse("tel:"+incno1));
And ensure the following permission is set:
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
Try this code may be working i am not tested:
Intent intent1 = new Intent(Intent.ACTION_CALL);
intent1.setData(Uri.parse("tel:" + incno1));
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.addFlags(Intent.FLAG_FROM_BACKGROUND);
context.startActivity(intent1);
You can add it in your xml file
android:autoLink="phone"
android:phoneNumber="true"
add this to your text view that links directly to call.
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:+123456"));
startActivity(intent);
} catch (Exception e) {
Log.e("SampleApp", "Failed to invoke call", e);
}
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
use permission in AndroidManifest.xml

Categories