No activity found to handle Intent - android.intent.action.OPEN_DOCUMENT - android

I am trying my hand on Storage Access Framework of android 4.4
I have developed a dummy app which fires an intent on start of the activity.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, READ_REQUEST_CODE);
Also I have developed another dummy app which serves as the file-provider.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.saf"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.saf.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="com.example.saf.MyFileProvider"
android:authorities="com.example.saf.documents"
android:exported="#bool/is_kitkat"
android:enabled="#bool/is_kitkat"
android:grantUriPermissions="#bool/is_kitkat"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
</application>
I have implemented the class MyFileProvider.
But when I launch the user-app (the one which fires the intent), I get the following error
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.OPEN_DOCUMENT cat=[android.intent.category.OPENABLE] }
I was just following developer docs of android. Any ideas what I might be doing wrong?
Edit:
Here is my latest Manifest.
Also do I need to have a "proper" implementation of the MyFileProvider "extends DocumentsProvider"? Can I just return null in the functions for now?

Add a mime type, or simply intent.setType("*/*").
This seems to be a known issue. setType() is required.
Edit: you also need to add android:enabled="true", note that you should reference it from values and not directly so as only to enable it for >=kitkat. So android:enabled="#bool/is_kitkat", <bool name="atLeastKitKat">false</bool> in /res/values/ and <bool name="atLeastKitKat">true</bool> in /res/values-v19/

To open all files add this line:
intent.setType("*/*") ;
and if you need to filter to display images add this line:
intent.setType("image/*");

Just cast your intent,
like,
Intent intent = new Intent("android.intent.action.GET_CONTENT");
((Intent)intent).addCategory("android.intent.category.OPENABLE");
((Intent)intent).setType("*/*");

Related

Android Permissions - Best Practices

I have two Android Applications, a permission provider and a requester.
The provider has the below manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionprovider"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<permission android:description="#string/permission_desc"
android:icon="#drawable/ic_launcher"
android:label="some permission"
android:name="com.example.permissionprovider.CUSTOM"
android:protectionLevel="normal" />
<!-- is the below tag required in the provider?-->
<uses-permission android:name="com.example.permissionprovider.CUSTOM"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.permissionprovider.MainActivity"
android:permission="com.example.permissionprovider.CUSTOM"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I hope it is wrong to set permissions to a launchable activity as the launcher won't have permissions to launch this activity.Is that correct?
Should the provider's manifest declare that the provider application needs the permission - com.example.permissionprovider.CUSTOM , or is it not required as the permission is defined in the same manifest?
Now I have the requester app which has the below manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionrequester"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="com.example.permissionprovider.CUSTOM"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.permissionrequester.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and the Requester tries to start the provider's activity.
Intent i;
PackageManager manager = getPackageManager();
try {
i = manager.getLaunchIntentForPackage("com.example.permissionprovider");
if (i == null)
throw new PackageManager.NameNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(i);
} catch (PackageManager.NameNotFoundException e) {
} }
If the provider app was installed first followed by the requester, then the requester will be able to launch the provider's Activity, but this doesn't happen if it's the requester which is installed first. How to get around this?
I hope it is wrong to set permissions to a launchable activity as the launcher won't have permissions to launch this activity.Is that correct?
Correct, the launcher will be incapable of starting that activity. However, it will still appear in the launcher, and therefore the user will get frustrated when they cannot start up your app.
Should the provider's manifest declare that the provider application needs the permission - com.example.permissionprovider.CUSTOM , or is it not required as the permission is defined in the same manifest?
You can define the <permission> in both apps, to deal with your last problem:
If the provider app was installed first followed by the requester, then the requester will be able to launch the provider's Activity, but this doesn't happen if it's the requester which is installed first. How to get around this?
Define the <permission> in both apps.
Also, if you are publishing both apps, and no third parties should be using your provider, please use a signature-level permission, not a normal-one. This will prevent anyone other than you from writing an app that can successfully hold the permission.

Making a shortcut to a class (not the MainActivity) on the Android Homescreen

I've been looking ALL DAY to no avail..I know there are several questions on this but I haven't been able to find one that works properly for me.
Basically, I have an activity (MainActivity), with a function to add a shortcut to the home screen. When I click the shortcut, I want it to open a different activity (NewActivity). The hold up here seems to be that it doesn't work right when I try to launch a different activity than the one from which the shortcut was made.
The shortcut is successfully made, but when I click it I get an "App isn't installed" toast message from the Android system.
Here's the code for adding the shortcut:
Intent shortcutIntent = new Intent();
shortcutIntent.setClassName("com.enceladus.myApp", "com.enceladus.myApp.NewActivity");
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Calculator");
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(MainActivity.this, R.drawable.calc));
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
MainActivity.this.sendBroadcast(addIntent);
EDIT: Here's my manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.enceladus.myApp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.enceladus.myApp.NewActivity"
android:label=""
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleInstance"
/>
</application>
NewActivity.class functions perfectly (I know because I've debugged it a lot), so that's not the problem.
Try making your manifest look like this for the NewActivity entry:
<activity android:name="com.enceladus.myApp.NewActivity"
android:label=""
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleInstance"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
also maybe try making the shortcut intent like this:
Intent shortcutIntent = new Intent(MainActivity.this, NewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN); //Not sure if you'll need this or not.
//remove the next line.
//shortcutIntent.setClassName("com.enceladus.myApp", "com.enceladus.myApp.NewActivity");
The other way that you can do this is by setting the android:exported flag to true.

android content activitynotfoundexception no activity found to handle intent - when trying to go to url

I am trying to write an app where you can type in an address and then you get redirected to google maps. (I suppose this is called implicit intent)
-I have created an intent to launch the main activity, which is the only activity in my app.
The Main activity consists of some text, an editfield and a button.
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.where_do_you_live"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
this is the code for the button:
public void Button1Click(View view)
{
try
{
addressField=(EditText)findViewById(R.id.address);
String address=addressField.getText().toString();
address=address.replace(' ','+');
Intent geoIntent=new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("geo:0,0?q=" + address));
startActivity(geoIntent);
}
catch(Exception e)
{
TextView tv=(TextView)findViewById(R.id.textView1);
tv.setText(e.toString());
//finding stuff
}
}
If you are testing this in emulator, things are different than in a device.
When you are creating your Android Virtual Device, you should select Google APIs as your target. If you do not have them installed, you can use SDK Manager to download it.
Have a look at this.

Selecting default action on Android

I am trying to build an application that would replace a default action on Android. The problem is that when action should be performed i get "Select Action" dialog with no checkbox to select it as default. I think i should be getting "Complete Action Using" dialog (which in turn has the checkbox). I do not understand how I can make Android to offer me the "Complete ..." dialog. My manifest file is as:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="si.cetrtapot.mobiris"
android:versionName="1.0"
android:versionCode="1" >
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc"
android:required="true" />
<application android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:debuggable="true" >
<activity android:name=".ReadTagActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc" />
</activity>
</application>
</manifest>
Can anybody tell me what is wrong?
The way intent-filters work is that the PackageManager has all these applications registered with it via the Manifest that is found per application. Specifically when an application falls un a certain Intent-Filter, it will then be added to the list of applications that have those kinds of Intent-Filters declared in their Manifest.
For instance say my application, handles the: Intent.ACTION_SEND this means that my application will show up in the list of application that hand particular action. Which would include, the default MMS/SMS application and any other applications the user has that has this, including MY application if the user has it installed.
You should begin by understanding what "default action" even means. Understanding this will help you how to solve your problem.
For your reference:
Intent
Intent.CATEGORY_DEFAULT
I do not believe that anything is wrong. I don't believe NFC intents were meant to have a default app unless you have very specific intent filtering for Ndef formatted cards. I did this for my job because we wanted just our app to pop up with our tag. Otherwise it would just be in a list all the time (which is annoying).

Android error "unable to find explicit activity class"

I have an android project with several packages. The structure of the packages in this case is com.WAPP.SetLocation is the package that contains the activity I want to run.
In my manifest, com.WAPP is considered the base package:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.WAPP"
android:versionCode="1"
android:versionName="1.0">
My activities are declared in my manifest as:
<activity android:name=".mainScreenActivity"></activity>
<activity android:name=".SetLocation.setLocationActivity"></activity>
The mainScreen activity displays fine, since it is inside the com.WAPP package. But when I try to run the setLocationActivity, I get the unable to find explicit class error. Here is how I have the intent parameters:
Intent i = new Intent();
i.setClassName("com.WAPP.SetLocation",
"com.WAPP.SetLocation.setLocationActivity");
startActivity(i);
The first parameter is application package not the package where the activity is.
You can invoke the Activity like this.
Intent i = new Intent();
i.setClassName("com.WAPP",
"com.WAPP.SetLocation.setLocationActivity");
startActivity(i);
It is preferred as SYLARRR suggested to have Android automatically figure that out for you. Hence the call as..
startActivity(new Intent(this, setLocationActivity.class));
It's recommended per java standards to have the package name all lower-cased and the class name as CamelCased.
If the new activity not in the same packet with MainActivity(you call from here?), try declare on manifest
<activity android:name="com.WAPP.SetLocation.setLocationActivity"></activity>
and in the caller
Intent intent = new Intent(this, setLocationActivity.class);
startActivity(intent);
Hope this helps!
In additional to the above answers make sure that your activities are declared inside application in manifest
<application
android:allowBackup="true"
android:label="#string/app_name"
android:supportsRtl="true">
<activity android:name=".mainScreenActivity"></activity>
<activity android:name=".SetLocation.setLocationActivity"></activity>
</application>
If i'm not mistaken, the i.setClassName("com.WAPP.SetLocation","com.WAPP.SetLocation.setLocationActivity"); should be i.setClassName(getBaseContext(),"setLocationActivity"); Reference
Also try this syntax:
startActivity(new Intent(MyActivity.this, setLocationActivity.class));
and try removing the starting dot from:
<activity android:name=".SetLocation.setLocationActivity"></activity>
Do it by this way:
Intent intent = new Intent();
intent.setComponent(
new ComponentName("com.WAPP", "com.WAPP.SetLocation.setLocationActivity"));
startActivity(i);
you should class ad to manifest.xml
for example of manifest.xml
in this example, i added SecondActivity.class
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<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/Theme.MyApplication">
<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=".SecondActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
In Xamarin Android, make sure that your Activity class has an Activity attribute
[Activity(Theme = "#style/MyTheme")]
public class MyActivity : ActivityBase
{
...
}
With that you are making sure that your activity is registered in AndroidManifest.xml
I had the same kind of issue in the project . It wasted me almost a full day . i tried all the solutions that are mentioned above , but none of the solutions worked for me .
After all the hard work i just "Rebuild" the project and "clean" The project and it worked perfectly .
Note:
Before going through all the process u just needed to have a try to these options.
First of all, make sure that you have created activity and not the class. And, if it is activity then go to the manifest.xml file and look at the path of that particular file.
This worked for me absolutely well!!
https://forums.xamarin.com/discussion/104102/android-content-activitynotfoundexception-unable-to-find-explicit-activity-class
this is for reference
in your manifest you declared it as
.SetLoction.setLocationActivity
but
the package name is com.WAPP.SetLocation
so you need to prefix that again.
Intent i = new Intent();
i.setClassName("com.WAPP.SetLocation",
"com.WAPP.SetLocation.SetLocation.setLocationActivity");
startActivity(i);
This might be due to not registering your next activity XML file in the manifest. Register your next activity XML file in the AndroidManifest.xml file
<activity android:name=".NextActivity" />
Hope it helps.
Thia might be problem if ImageView is used :(
Intent intent = new Intent(context,ImageView.class);
intent.putExtra("imageurl",clients_document_return.getUrl());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(intent);
and your class name might me Imageview.class
so first check all small capital in class name
Thanks :)

Categories

Resources