I am trying to create a very simple QR input method in Android. Far from being actually runnable in "production", I am trying to run my custom QR keyboard application on my Nexus 6 device, at least to see where it will crash.
However, after deploying the APK to the device I cannot choose my custom input.
Following is the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.zighinetto.qrkey" >
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service
android:name=".services.QrInputService"
android:enabled="true"
android:permission="android.permissions.BIND_INPUT_METHOD" >
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="#xml/ime" />
</service>
<activity
android:name=".ui.SettingsActivity"
android:label="#string/title_activity_settings" >
</activity>
</application>
</manifest>
And... ime.xml
<?xml version="1.0" encoding="utf-8"?>
<input-method
android:isDefault="true"
xmlns:android="http://schemas.android.com/apk/res/android">
</input-method>
So far I have:
- Enabled CAMERA permission because I need to use the camera
- Created the IME service and linked it to the BIND_INPUT_METHOD permission, so that only the system can bind to it
- NOT declared the BIND_INPUT_METHOD as permission used by my application, because only the system needs that permission.
I expect the new QR input service to be visible in Android's "Language and input" screen, however I cannot see it.
What is wrong in my manifest?
Related
I have a SIM card with an applet (cardlet) on it. If I can set the default secure element in an Android device to UICC I can send commands via contactless interface to UICC.
My NFC reader sends an APDU with a "SELECT AID A0000001234567890" to the NFC controller which shall send it to my applet on the UICC secure element (access control has been taken care of).
Now I want to make this work for devices where I cannot set the default secure element to UICC.
If I understood everything correctly, as I do not need an Android application for this in principle, I nevertheless have to make use of a dummy Android application and declare a so-called "off-host service" in its manifest.
Can someone guide me what I need to do to route the APDUs that select the AID of my applet installed on the secure element and the subsequent APDUs to the UICC secure element?
Here is my first attempt, but maybe someone has a working example for me or some guidance/corrections.
AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
<service android:name=".OffHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.off_host_apdu_service"
android:resource="#xml/apduservice"/>
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
</service>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Echo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<uses-library
android:name="com.android.nfc_extras"
android:required="true" />
</activity>
</application>
apduservices.xml:
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="#string/servicedesc">
<aid-group android:description="#string/subscription" android:category="payment">
<aid-filter android:name="A0000001234567890"/>
</aid-group>
</offhost-apdu-service>
Your start looks fine and using an offhost-apdu-service should work fine on devices that support routing card emulation communication to a secure element. Note that some devices simply do not support this though.
There are some issues with your XML files though:
A card emulation service in category payment must declare a service banner drawable resource. The service banner should be a graphic file (e.g. a .png file) with dimensions of 260 x 96 pixels.
<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/servicedesc"
android:apduServiceBanner="#drawable/servicebanner">
<aid-group android:category="payment"
android:description="#string/servicedesc" >
<aid-filter ... />
</aid-group>
</offhost-apdu-service>
Services must be declared within the application tag in your manifest file (note that I also change the name of the service to avoid conflicts with the naming of the framework class):
<application ...>
<activity ...>
...
</activity>
<service android:name=".MyOffHostApduService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" />
</intent-filter>
<meta-data android:name="android.nfc.cardemulation.off_host_apdu_service"
android:resource="#xml/apduservice" />
</service>
</application>
Besides declaring the service in your manifest, you also need to actually create the Java implementation for the service. Something like:
public class MyOffHostApduService extends OffHostApduService {
public IBinder onBind(Intent intent) {
return null;
}
}
<uses-feature ...> and <uses-permission ...> elements must be direct child elements of the <manifest> element (i.e. on the same level as the <application ...> element. They must not be used inside other tags (like the service tag in your case):
<manifest ...>
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
<application ...>
The <uses-library ...> element must be a direct child of the <application ...> element. However, you probably don't use this library anyways and can completely drop that.
Finally, note that the AID in your example is not valid since it does not align on full bytes. A valid AID would, for example, be A00000012345678900. (Though I assume that this just happend during masking your original AID for the example, right?)
I am making an app that communicates with a piece of usb hardware made by my company (this is the only app allowed to talk to the usb accessory, it's not a public api). I am having difficulties setting up the proper launch modes in the manifest.
There are three components to the app: the main activity, a login activity, and the USBService.
I'm assuming the intent for the main goes to the login activity, and the intent for the usb goes to the USBService, but I am not sure if I do this, will this start the service if the app is not running? More over, if it does, how do I fetch an already existing service?
What type of structure should I be looking at for the manifest file? (specifically, intent-filters, and appropriate launch modes... I've read a few documents about the launch modes but I am still not sure I quite understand... There should only ever be at most one instance of each activity/service, and they need to communicate together.
edit: it is not necessary for communications to start before the app is open, nor is it necessary to launch the app automatically when the usb is connected.
edit: my manifest as it stands, looks like:
<uses-feature android:name="android.hardware.usb.accessory" />
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="mainpackage.MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
<activity
android:name="mainpackage.LoginActivity"
android:label="#string/title_activity_login"
android:windowSoftInputMode="adjustResize|stateVisible" >
</activity>
<service android:name="updater.USBService"
android:exported="false" >
<!--
-->
</service>
</application>
in your manifest add
<manifest ...>
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk android:minSdkVersion="12" />
In this case, the following resource file should be saved in res/xml/device_filter.xml and specifies that any USB device with the specified attributes should be filtered:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
Hope this help.
Your manifest looks good,
I think you make a good choice for putting the intent-filter "android.hardware.usb.action.USB_ACCESSORY_ATTACHED" in the mainActivity and start the application in this activity,
and again I think it's a good choice to start your mainActivity in SingleTop launch mode,
because if an instance of the mainActivity already exists at the top of the current task, the system going to launch this activity, no new instance of this activity will be created.
For a best understanding of the different launch mode available in android,
I think this link may help you :
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
To make a long story short I think you'll be all set with this manifest as is.
To Use Android Devices min SDK version should be set to 12 and need to declare following line in AndroidManifest.xml file
<>
<uses-sdk android:minSdkVersion="<version>" />
...
<application>
<uses-library android:name="com.android.future.usb.accessory" />
<activity ...>
...
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
</application>
I have a weird problem. I set the screen orientation in android manifest and it works on emulater but not on the actual device. I also changed the orientation programmatically and still the problem persists. My manifest is as follows -
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.rotatedsignage"
android:versionCode="1"
android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.rotatedsignage.MainActivity"
android:configChanges="orientation"
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>
</activity>
<receiver
android:name="com.example.rotatedsignage.BootReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
What is wrong with my code? The code I used -
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
any help is appreciated. Thanks in advance.
Check in your device under Settings section that whether your AutoRotate screen is locked or not.If it is locked then uncheck it.
Hope this helps.
First check your device settings as Siddharth Vyas suggest you, then make some changes like following in your config file.
<preference name="orientation" value="default" />
default means both landscape and portrait are enabled or else you can put portrait and landscape whatever you want in place of default. Hope this helps.
I restarted the app in my android phone and screen rotation started to work. I think, for a real device, if changes are made in app.json, then app needs to be restarted to see the changes.
So im kinda new to android programming and i dont really know why i cant run the main activity when i have a permission tag under the activity. this is my code under the manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lab08b_awahla"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="com.example.DANGEROUS_ACTION" />
<permission
android:name="com.example.DANGEROUS_ACTION"
android:label="permission"
android:protectionLevel="dangerous" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.lab08b_awahla.MainActivity"
android:label="#string/app_name"
android:permission="com.example.DANGEROUS_ACTION" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.example.DANGEROUS_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
This is obvious. If you are providing a security tag for activity anyone who wants to launch this activity has to have such privilege. Home screen app doesn't have (even don't known) your permission tag so this is a problem.
According to the docs for the <activity> tag
android:permission
The name of a permission that clients must have to launch the activity or otherwise get it to respond to an intent. If a caller of startActivity() or startActivityForResult() has not been granted the specified permission, its intent will not be delivered to the activity.
This leads me to think that you misunderstand the use of this attribute.
In my Android Application I have a Google MapView Activity and I am facing the following Error:
MapView: Couldn't get connection factory client
At first: I have a right Maps Key and the Internetpermission and the Map is displaying fine on Emulator and Device. The thing that I am confused about is that although the map works, the above error displays.
On the Device sometimes the Map loads and displays correctly and 1 minute later, if start to zoom and pinch the map the map does not continue loading and throws the error.
If I switch off and on again the mobile network on the device the map works fine again.
Edit: my Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="de.incowia.mobileschatzsuche"
android:versionCode="1"
android:versionName="2011.10.07">
<!-- We're supporting AndroidSDK 7 -->
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="7"/>
<!-- We need access to the internet for loading maps -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- We're using both, network and GPS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application android:icon="#drawable/icon" android:label="#string/app_name"
android:theme="#style/DefaultTheme">
<!-- 4 test -->
<uses-library android:name="android.test.runner" />
<!-- We're using Google Maps API -->
<uses-library android:required="true" android:name="com.google.android.maps" />
<!-- Dashboard -->
<activity android:name=".MobileSchatzsucheActivity" android:label="#string/app_name" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Maps Activity -->
<activity android:name=".GoogleMapsActivity" />
<!-- Schatzliste Activity -->
<activity android:name=".SchatzlisteActivity" android:launchMode="singleTask"/>
<!-- Schatzdetails Activity -->
<activity android:name=".DetailsActivity"/>
<!-- MyTreasuresCoverFlowActivity -->
<activity android:name=".MyTreasuresCoverFlowActivity"/>
<!-- Preferences Activity-->
<activity android:name=".PreferencesActivity"
android:theme="#android:style/Theme"/>
<!-- FileBrowser Activity -->
<activity android:name=".FileBrowserActivity"
android:theme="#android:style/Theme"/>
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="de.incowia.mobileschatzsuche"
android:label="test test" />
</manifest>
Just try to give these Two Permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Because when you zoom in/zoom out the Google map goes accordingly in/out, so for that we need to give such permission.
It will work then