Activity Access Restriction Implementation in a Monodroid Application - android

I have a requirement where I need to restrict access to an activity of a Monodroid Application. Hence i tried a spike where the application IntentSayHello would have an access restricted Activity called SayHelloActivity. As the first step i defined the permission tag in the AndroidManifest.xml of the application as below:
...
...
</application>
<permission
android:name="intentsayhello.permission.SAYHELLO"
android:protectionLevel="signature" android:label="#string/permlbl_restricted"
android:description="#string/permdesc_restricted">
</permission>
</manifest>
Please note that i'm using protectionLevel = signature which means that any other application signed with the same certificate as IntentSayHello can only access the restricted activity.
Now i coded the SayHelloActivity as below:
[Activity(Label = "SayHelloActivity", MainLauncher = true, Icon = "#drawable/icon", Permission = "intentsayhello.permission.SAYHELLO")]
[IntentFilter(new string[] { "companyXYZ.intent.sayhello.MAIN" },Categories = new string[]{Intent.CategoryDefault},
DataMimeType = "vnd.companyXYZ.say.hello/vnd.companyXYZ.activity")]
public class SayHelloActivity : Activity
{
.....
.....
}
After this i tested with a client application by invoking SayHelloActivity of IntentSayHello through an implicit intent and i got SecurityException as expected.
Permission Denial: starting Intent { act=companyXYZ.intent.sayhello.MAIN typ=vnd.companyXYZ.say.hello/vnd.companyXYZ.activity cmp=IntentSayHello.IntentSayHello/intentsayhello.SayHelloActivity }
from ProcessRecord{4094f850 9126:DiffKeyHello.DiffKeyHello/10097} (pid=9126, uid=10097) requires intentsayhello.permission.SAYHELLO
Now if i want my client Application to be given access to the SayHelloActivity of the restricted application, i'm supposed sign my client application with the same keystore (certificate) and also mention in the AndroidManifest.xml of the client application as below:
...
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="intentsayhello.permission.SAYHELLO" />
</manifest>
But when i did both of this, the client application still could not invoke the SayHelloActivity and same SecurityException is thrown.
I would like to know the directions/solution to this issue.
Thanks

After Googling around, hit upon this page: http://lists.ximian.com/pipermail/mono-bugs/2011-January/108218.html
I took the cue from this page that the need to be put into the Client's AssemblyInfo.cs. The syntax would be:
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission("intentsayhello.permission.SAYHELLO")]
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
It worked from then on.

Further search in mono android forum, i found that another way of doing this is to explicitly add the androidmanifest.xml in the .csproj file as below:
<PropertyGroup>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup>
Either of the above solutions works, only i do not know which/both are correct practice.

Related

Android: Problem with the camera opening in webview

After a few days struggling with opening camera within webview I decided to ask the question here.
So,
I have a webview in my app which open a web page where is a camera. To forestall the questions, I do not have access to the website code.
I work on the android sdk 30 and Pixel 3 api 30. I tried it to open also on old android SDKs (23 - 24) or on the newest android 12. Tried to add android:requestLegacyExternalStorage with target sdk version 29.
When i try to open the given website in the chrome on my emulator it works correctly.
I think it can be problem with camera permissions but i have no idea how to check it. Calling requestPermissions for the camera also didn't help me.
And I just keep getting this error all the time:
E/cr_VideoCapture: getCameraCharacteristics:
java.lang.IllegalArgumentException: supportsCameraApi:2340: Unknown camera ID 0
at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:1001)
at android.hardware.camera2.CameraManager.getCameraCharacteristics(CameraManager.java:449)
at ft0.i(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:1047)
at org.chromium.media.VideoCaptureFactory.isLegacyOrDeprecatedDevice(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:1339)
at org.chromium.media.VideoCaptureFactory.getFacingMode(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:93)
Caused by: android.os.ServiceSpecificException: supportsCameraApi:2340: Unknown camera ID 0 (code 3)
at android.os.Parcel.createExceptionOrNull(Parcel.java:2387)
at android.os.Parcel.createException(Parcel.java:2357)
at android.os.Parcel.readException(Parcel.java:2340)
at android.os.Parcel.readException(Parcel.java:2282)
at android.hardware.ICameraService$Stub$Proxy.supportsCameraApi(ICameraService.java:906)
at android.hardware.camera2.CameraManager.supportsCameraApiLocked(CameraManager.java:1054)
at android.hardware.camera2.CameraManager.supportsCamera2ApiLocked(CameraManager.java:1030)
at android.hardware.camera2.CameraManager.getCameraCharacteristics(CameraManager.java:422)
at ft0.i(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:1047) 
at org.chromium.media.VideoCaptureFactory.isLegacyOrDeprecatedDevice(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:1339) 
at org.chromium.media.VideoCaptureFactory.getFacingMode(chromium-TrichromeWebViewGoogle6432.aab-stable-489612734:93) 
Thanks :)
Make sure to add permission in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA"/>
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
Then in your activity, You can check camera permission like below
if(ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.CAMERA)==PackageManager.PERMISSION_GRANTED) {
}
Inside this condition you can use android.provider.MediaStore.ACTION_IMAGE_CAPTURE to get the list of camera intent from packagemanager

Unit test for uses-permission permissions

I'm trying to figure a way to test if <uses-permission android:name="android.permission.INTERNET" /> is set in AndroidManifest.xml, but I can't. Is it possible to do that? Right now I'm using ActivityInstrumentationTestCase2.
I'm trying to learn testing in Android Studio, and I think that testing that certain uses-permission permissions are set is a good idea at the start of testing the application.
This is how I ended up doing it:
Context testContext = getActivity().getContext();
PackageManager pm = testContext.getPackageManager();
expected = PackageManager.PERMISSION_GRANTED;
actual = pm.checkPermission(Manifest.permission.<PERMISSION_YOU_ARE_LOOKING_FOR>, testContext.getPackageName());
assertEquals(expected, actual);

Mobile backend starter continuous query never returns

I've written an Android client for a mobile backend starter app according to this tutorial. Everything works up to the section implementing Continuous Queries.
I've written a query and I'm calling it from the correct place in the code (onPostCreate()), however the query never returns any data.
I don't believe this is an authentication problem because I'm able to make other calls successfully.
Here is the code which never returns a result:
CloudCallbackHandler<List<CloudEntity>> handler = new CloudCallbackHandler<List<CloudEntity>>() {
#Override
public void onComplete(List<CloudEntity> results) {
for (CloudEntity entity : results) {
UserLocation loc = new UserLocation(entity);
mUserLocations.remove(loc);
mUserLocations.add(loc);
drawMarkers();
}
}
#Override
public void onError(IOException e) {
Toast.makeText(getApplicationContext(), e.getMessage(),
Toast.LENGTH_LONG).show();
}
};
CloudQuery query = new CloudQuery("UserLocation");
query.setLimit(50);
query.setSort(CloudEntity.PROP_UPDATED_AT, Order.DESC);
query.setScope(Scope.FUTURE_AND_PAST);
getCloudBackend().list(query, handler);
With the debugger I've verified that the getCloudBackend().list() line executes, but the onComplete() method is never hit, and neither is onError().
Here is an example of a call that works perfectly:
UserLocation self = new UserLocation(super.getAccountName(),
gh.encode(mCurrentLocation));
getCloudBackend().update(self.asEntity(), updateHandler);
Essentially, getCloudBackend().update() works, while getCloudBackend().list() does not.
I should also add that I've downloaded the full source from the github repo linked in the tutorial, and the same problem exists with that code.
I've also tried re-deploying the backend server multiple times.
Ok so I have finally fixed the problem! The issue is both in the manifest and in the class GCMIntentService.java
In the manifest the GCM is registered as a service and belongs to a package. By default this service is a part of the default package com.google.cloud.backend.android. When you create a new package and have all your client code in there, you need to move the GCMIntentService.java class into that new package and in the manifest modify the service and broadcast receiver
<service android:name="yourpackagename.GCMIntentService" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="yourpackagename" />
</intent-filter>
</receiver>
Any other permission that comes with the default package name should also be updated to the main package name. This doesn't need to be modified if you're only going to use that one default package that comes with the mobile backend starter.
Regarding the GoogleAuthIOException I received that as well initially. So I redid all the steps to enable GCM and authentication. Things to keep in mind though are that I still followed the tutorial and went with Web Application -> Generic when registering the GCM server key and Web Client ID. Also another key thing to keep in mind when registering for the Android Client ID is that with your SHA1 fingerprint it also needs a package name. Again the package name has to be your main client package if you're using more than one package for your project. You can get the project number that goes in the Consts.java (and it's required to register GCM) from the old Google API console and the project ID from the new cloud console. The Web client ID also goes in the Consts.java file and also in that same file you have to enable auth by changing
public static final boolean IS_AUTH_ENABLED = false;
to
public static final boolean IS_AUTH_ENABLED = true;
Hope this helps.
So I am also getting the SAME EXACT problem you are. getCloudBackend().update() works for me, and not only with the geohasher class, I also tried to send updates to the cloud with myLocation.toString() where myLocation is a LatLng and it gets updated fine.
Sorry for not giving you the actual solution to your problem. It's a really odd situation that the same exact code worked in the Google I/O demo but not when we (and I followed the tutorial very thoroughly) actually try it out. I feel that this is a server problem if anything.
Thanks for reporting this -- sorry you are having a problem. THe most likely problem is in configuring GCM. Can you verify you have GCM enabled on the project and all the setup steps where done correctly? Maybe try to send a message and see if that works?

Android Permission denial in Widget RemoteViewsFactory for Content

I have a widget which I am trying to use to display information from my app's local database inside of a listview.
I'm using the RemoteViewsService.RemoteViewsFactory interface to load my list's contents. If I run the block of code which reloads the list in the onDataSetChanged method. the app crashes with the following message:
11-01 16:40:39.540: E/ACRA(27175): DataDisplay fatal error : Permission Denial: reading com.datadisplay.content.ContentProviderAdapter uri content://com.datadisplay.provider.internalDB/events from pid=573, uid=10029 requires the provider be exported, or grantUriPermission()
However, this same code run in the class's constructor works just fine. Of course, I need to have this also work in the onDataSetChanged method for updating and stuff.
Here is my provider's entry in the manifest:
<provider android:name="com.datadisplay.content.ContentProviderAdapter"
android:authorities="com.datadisplay.provider.internalDB"
android:exported="true"
android:enabled="true"
android:grantUriPermissions="true">
<grant-uri-permission android:pathPattern="/events/"/>
</provider>
I am both exporting it AND granting Uri permissions like the error message requests, but it still fails. I found this question, where the guy had an issue but eventually removes his custom permissions and it worked. I don't have any custom permissions like that, but still no luck:
Widget with content provider; impossible to use ReadPermission?
If anyone has insight I'd be really grateful, this is getting incredibly frustrating, haha.
This is happening because RemoteViewsFactory is being called from a remote process, and that context is being used for permission enforcement. (The remote caller doesn't have permission to use your provider, so it throws a SecurityException.)
To solve this, you can clear the identity of the remote process, so that permission enforcement is checked against your app instead of against the remote caller. Here's a common pattern you'll find across the platform:
final long token = Binder.clearCallingIdentity();
try {
[perform your query, etc]
} finally {
Binder.restoreCallingIdentity(token);
}
Put this in your onDataSetChanged() method:
Thread thread = new Thread() {
public void run() {
query();
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
}
Fetch data from the database inside query() method. I do not know why fetching data in a separate thread helps get around this problem, but it works! I got this from one of the Android examples.
If this only happens for 4.2 and not the rest, you need to set the android:exported="true", because the default is changed:
http://developer.android.com/about/versions/android-4.2.html
Content providers are no longer exported by default. That is, the default value for the android:exported attribute is now “false". If it’s important that other apps be able to access your content provider, you must now explicitly set android:exported="true".

Android Visualizer class throwing runtime exception

I am using AndroidFX Visualizer class in my demo app to read FFT but when i try to create object of that class its throwing Runtime exception (java.lang.RuntimeException: Cannot initialize Visualizer engine, error: -1). Player class is my custom class for playback control and using same Player class i have implemented equalizer class and that's working fine. Do i need to add any permission in manifest file?
Player mediaPlayer = Player.GetInstance();
mediaPlayer.LoadFile("song.mp3");
mediaPlayer.Play();
try{
visual = new Visualizer(mediaPlayer.GetAudioSessionID()); // this line causing Exception
visual.setEnabled(true);
visual.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
}
catch(Exception ex)
{
Log.e("Visual Ex", ex.getMessage());
}
That was due to my foolish mistake, that feature requires <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission> permission. thanks
I know this is a very late answer but I also struggled with this problem and I want to share my experiences.
First, as the answer above mentioned, the permissions
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
and, if audio source 0 is used (Visualizer(0); //system mix),
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
are needed. After adding the permissions to my app and installing the (new compiled) app again, my app still crashed. I found out, that the device has to be restarted, to use the Visualizer without any exception (for whatever reason). So if you develop an app and get this exception, a restart could be required after adding the permissions to the app .

Categories

Resources