API 30
This is going to all sound very scrambled, because I've very conf
The following works perfectly fine, it loads the image into 'imCardImage' widget without problem.
val getContentCardImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
imCardImage.setImageURI(uri) // Handle the returned Uri
cImageCardStr = uri.toString()
Log.d("EditCards","URI = "+uri.toString())
Log.d("EditCards","(mydecklist) URI = "+mydecklist[cCardPosition].c_image)
}
The problem appears when, I exit the app and restart it/go to another activity within the same application, all the images are gone it's as if I had temporary permission while the activity was active, in the area where you can select images and revoked the instant that activity is terminated, and yet I've requested permission from the use and been granted it.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I did get this error; Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider but for some odd reason it's stopped happening for some unknown reason.
override fun onBindViewHolder( holder: ViewHolder, position: Int ) {
holder.cardTitle.text = "[$position] "+mydecklist[position].c_title
holder.cardMessage.text = mydecklist[position].c_message
holder.cardImage.setImageURI(mydecklist[position].c_image.toUri())
}
The above is supposed to load the image from mydecklist[#].c_image in to a RecycleView / CardView, but is blank when starting the app.
14727-14727/com.example.cardgamexxx E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.cardgamexxx, PID: 14727
java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{bc01e1c 14727:com.example.cardgamexxx/u0a734} (pid=14727, uid=10734) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
-- error is back, thanks to "mehul bisht" no actually I did want that back :) see my reply to your comment.
// Permissions
permissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
readPermissionGranted = permissions[Manifest.permission.READ_EXTERNAL_STORAGE] ?: readPermissionGranted
}
requestPermissions()
Permission already requested, if there is some other permission I should be asking for I'd love to know.
EDIT 2
Pretty sure I might have an idea, I might be entirely wrong though!
registerForActivityResult()...
Above when the user selects the image the image is resolved? uri is valid? I have permission at this point? no idea why that works but it works.
holder.cardImage.setImageURI(mydecklist[position].c_image.toUri())
That's the deploy line that sends the image to the cardImage widget, but is in a mutable list as a type string which I am converting to a Uri. I suppose that is okay. however it doesn't work when loading the application from a restart or just switching to another activity in the same application and back again, so either I need to resolve the uri so that it's valid again or takepermission to have access to it always.
NB: it would be better if I had my own folder that users could drop files in that I had total access to but I don't know how to do that so, I have to go the overly convoluted obtuse route.
Related
Im trying to transmit phone's camera preview to a textureView in app. When i start the method i get the following error in logcat and the app crashes.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.camera2.CaptureRequest$Builder android.hardware.camera2.CameraDevice.createCaptureRequest(int)' on a null object reference
This is the code.
try {
//[0] Usually is the back cam but may need to play with it.
ActivityCompat.requestPermissions(CameraActivity.this ,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},PackageManager.PERMISSION_GRANTED);
Log.d("asd","here");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
Log.d("asd","OOOOOPPPSs");
return;
}
Log.d("asd","BBBBBBBBBBBBBBBBBB");
cameraId=cameraManager.getCameraIdList()[0];
Log.d("asd","AAAAAAAAAAAAAAAAAAAAAAA");
cameraManager.openCamera(cameraId, stateCallbackForCamera, null);
}catch (Exception a){
a.printStackTrace();
}
This is the log output i get.
2022-10-19 12:56:06.227 11217-11217/com.example.testapp D/asd: here
2022-10-19 12:56:06.227 11217-11217/com.example.testapp D/asd: OOOOOPPPSs
If i bypass the permission check by changing the if statement to
ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
The new log output i get becomes this
2022-10-19 12:47:19.959 10777-10777/com.example.testapp D/asd: here
2022-10-19 12:47:19.959 10777-10777/com.example.testapp D/asd: BBBBBBBBBBBBBBBBBB
I have two questions, first; why does the permission check fail? (The app wont show popup to ask for permissions).
Second; I believe the code
cameraId=cameraManager.getCameraIdList()[0];
Is somehow breaking the app, why is that and how can i fix it? Perhaps cameraManager is null?
This is how the cameraManager is assigned, i took this from a video i saw and it was working fine for that person but im not familiar with these concepts so any help is appriciated.
cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
EDIT: FOUND THE CAUSE AND FIX FOR MY OWN SITUATION, NOW RAN INTO ANOTHER QUESTION, CHECK MY FIRST ANSWER.
I found the cause; Like the idiot i am, i forgot to add camera permission request to the request line. Once this was added, the app would run perfectly fine. Although i have another question now; The first time i ran the app after adding the camera request, The permission request popped up on the screen and when i accepted it, the camera still wouldnt work for a few seconds then the app reset to the main activity by itself only then on the second try it would work normally. Why is that?
A bit more detail; the app consists of several activities, the main activity is basically empty only with a button and speech recognition, it directs you to the camera activity where everything camera related takes place.
Background: I was trying out the new Tiles and TileService and decided to recreate the USB Tethering tile from CyanogenMod. I used reflection to access Connectivity manager's methods.
Problem: One Such method is the isTetheringSupported() which causes java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query user
So I added the permissions to the manifest but every time I use pm grant it returns "Permission is not a changeable permission type"
According to this I should not get this error when signed with the debug key.
Question: How do I get those permissions?
UPDATE:
Via Xposed it is possible to hook into the PackageManger and remove the below check and then do pm grant... to successfully grant whatever permission. If someone sees this and needs help to do so comment below I'll help you out.
OLD ANSWER
This code in the source
boolean isDevelopment =
((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
doesn't check if your app is in development mode. It checks if the permission you are requesting has the protectionLevel attribute (set in manifest) set to development.
And the permission you are trying to get seems not to have any elements declared in the manifest that could pass this check:
if (!isNormal && !isDangerous && !isDevelopment) {
throw new SecurityException("Permission " + bp.name
+ " is not a changeable permission type");
}
Just stumbled upon this with another permission. Seems there's sadly no way to get it.
This has been asked a couple of times on Unity Questions, but never answered.
All I need to do is creare an Android pluugin which downloads few files from given urls and show a downloading progress in notification panel. Downloading should continue even if my Unity application is out of focus.
(source: cuelogic.com)
Here is a peice of code that I have right now:
void DownloadFiles(string[] urls)
{
foreach(var url in urls)
{
StartCoroutine(DownloadFile_CR(url));
}
}
IEnumerator DownloadFile_CR(string url)
{
WWW www = new WWW(url);
while(!www.isDone)
{
yield return null;
}
if(www.error == null)
{
//file downloaded. do something...
}
}
These are some texture files. So How do I get the texture result back from native android code?
Any king of help is appreciated.
I had the same problem. At first, I used a service that worked in the background and downloaded the files I needed, including calculating progress and on complete events.
Then, I made my plugin a little more simple and easy to use. You make an instance of a Java object, providing it with the GameObject name and method name for the responses. I used json to serialize and deserialize java and C# objects, because only strings can be passed between Unity's MonoBehaviour objects and java objects.
Here is how the downnload looks in the android plugin:
Uri Download_Uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(true);
//Set the local destination for the downloaded file to a path within the application's external files directory
String[] split = url.split("/");
request.setDestinationInExternalFilesDir(activity, null, split[split.length-1]);
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle("Downloading " + title);
//Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription("Downloading " + name);
request.setVisibleInDownloadsUi(false);
//Enqueue a new download and get the reference Id
long downloadReference = downloadManager.enqueue(request);
Then you could send back to unity the reference Id so you can get the progress and check if a file is still downloading once your app is been restarted (use SharedPreferences \ PlayerPrefs to store them)
If you want it to continue even when unity is not in focus then you cannot do it in C# in Unity with the WWW class.
If i wanted to do this i would probably write a native Android plugin that starts a download service.
From the official google docs:
A Service is an application component that can perform long-running
operations in the background, and it does not provide a user
interface. Another application component can start a service, and it
continues to run in the background even if the user switches to
another application.
Services are not that complex, you start them with Intents just as you would an activity and there are lots of examples online for this type of service.
Here is the official Android documentation regarding services: https://developer.android.com/guide/components/services.html
I have an app which I recently uploaded to the Play Store, with Crashlytics enabled. Within this app there is an activity called StartQuizActivity, which was created during development but is currently unused. The activity is still declared in the manifest, but there are no intents within the app which invoke it.
I received a crash report with the stack trace suggesting that a device had attempted to launch this activity, which resulted in an IllegalArgumentException, suggesting the required objects weren't passed with the intent:
Fatal Exception: java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.fractalwrench.acidtest/com.fractalwrench.acidtest.activities.StartQuizActivity}:
java.lang.IllegalArgumentException: No extras supplied to
startQuizActivity!
StartQuizActivity.java
#Override protected void onCreate(Bundle savedInstanceState) {
aminoAcid = getIntent().getExtras().getParcelable(AMINO_ACID);
super.onCreate(savedInstanceState);
if (aminoAcid != null) {
// do things
} else {
throw new IllegalArgumentException("No extras supplied to startQuizActivity!");
}
Why would a device be able to launch this activity, given that there is no way to launch StartQuizActivity using the app's UI? I have noticed that the device was a rooted Nexus running API 21, and have seen similar crashes for other activities in the app. I have been unable to reproduce the crashes on any device, even after trying MonkeyRunner.
Is this some form of automated testing by Google or perhaps a user with a very specific device setup? Any thoughts would be appreciated.
AndroidManifest.xml
<activity
android:name=".activities.StartQuizActivity"
android:label="#string/activity_title_prepare_for_quiz" />
When you add an activity to your manifest with android:exported="true" (as is the default for activities), it becomes part of your public API that any app can call.
Understandably so, it is quite rare for other apps to explicitly start a random Activity from another app without reason, but apps such as Tasker do allow end users to do exactly that.
You can either
Remove the activity from the manifest - this obviously removes any ability to start it at all
Add android:exported="false" - this ensures that other apps cannot start the Activity
Call finish() if no extras were supplied, immediately stopping the activity.
I am developing an application where i have file uri as well as bt device address with me. I need to send the file to the defined bt device. But, the device picker screen should not be shown. It should directly start the device sending.
Obviously, intent:ACTION_SEND is not an option here, as it will show the chooser dialog. The main intension of the application is to bypass the chooser dialog and enable user to send selected file to selected device directly.
So, i was trying the following solution suggested in stack-overflow:
/*BluetoothDevice device;
String filePath = Environment.getExternalStorageDirectory().toString() + "/file.jpg";
ContentValues values = new ContentValues();
values.put(BluetoothShare.URI, Uri.fromFile(new File(filePath)).toString());
values.put(BluetoothShare.DESTINATION, device.getAddress());
values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_OUTBOUND);
Long ts = System.currentTimeMillis();
values.put(BluetoothShare.TIMESTAMP, ts);
Uri contentUri = getContentResolver().insert(BluetoothShare.CONTENT_URI, values);*/
But unfortunately, it is not working. After getContentResolver().insert, there is no action taken. Needless to say, i have tried various permissions and other stuffs, but to no effect.
So, people who have used this code, please provide your suggestions. Any help to meet the requirement will be very much appreciated.
Does it produce any exception? Please share your Logcat output.
By the way, make use you have the following permission in AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH"/>
If you are doing a device discovery, add this too in the manifest file
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
I also found this problem. I can show some evidence to solve this problem. After trying this code check outbound transfer queue of your device (to open it, Send a file manually to a device and click the notification icon). Then you can see device has tried to send objects and those were failed. Click on one failure message and you can see pop-up with no file path. I think the problem is though here we are setting the file path using URI to the contentValues it will not be checked in the process. We have to do some thing for this.