I am attempting to access and retrieve all of the phone numbers for a particular contact (not all contacts), and am continuously running into the same permissions error despite having properly added necessary permissions.
I restarted Android Studio
I checked the syntax of my declaration
I checked for duplicate activity declarations
Yet the problem persists.
My log is shown here:
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 uri content://com.android.contacts/data/phones from pid=30288, uid=10127 requires android.permission.READ_CONTACTS, or grantUriPermission()
And apparently the permission issue occurs at the indicated line in this setup:
if (reqCode == REQUEST_CONTACT_PICKER) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri contactData = data.getData();
try {
String id = contactData.getLastPathSegment();
Cursor phoneCur = getContentResolver()
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, //----- -This one- ---------
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = ?", new String[] { id },
null);
For reference here is my manifest, the issue is occurring in Text_main.
<?xml version="1.0" encoding="utf-8"?>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<activity
android:name=".StartMenu"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Text_main"
android:label="#string/title_activity_text_main" >
</activity>
<activity
android:name=".Call_main"
android:label="#string/title_activity_call_main" >
</activity>
</application>
I am probably making a stupid and/or beginner's error as I am mostly splicing snippets (I am out of my basic comfort zone). I appreciate any help and/or constructive criticism.
By the way my code for retrieving the contacts was adapted from the top answer posted here:
All phone numbers of one contact for startActivityForResult
<uses-permission> needs to be an immediate child of <manifest>, as a peer to <application>. It cannot be a child of <application>.
Related
I try to create a background service with no user interface and I created it with BroadcastReceiver and added my necessary things in the manifest file. Then I configure Nothing as written in the link. I'm testing on an Android emulator, when I execute my app nothing happen and the service is not starting. Where is my problem?
Here is my manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.myapplication22">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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.MyApplication22">
<service android:name=".MyService" />
<receiver
android:name=".StartReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Here is my BroadcastReceiver
override fun onReceive(context: Context, intent: Intent) {
Log.i("MYSERVICE","override fun onReceive(context: Context, intent: Intent)")
if (intent.action == Intent.ACTION_BOOT_COMPLETED ) {
Intent(context, MyService::class.java).also {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startService(it)
return
}
context.startService(it)
}
}
}
Here is my Service
class MyService : Service() {
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent != null) {
println("MYSERVICE STARTED AUTOMATICALLY")
}
return START_STICKY
}
override fun onCreate() {
super.onCreate()
println("MYSERVICE override fun onCreate() {")
}
override fun onDestroy() {
super.onDestroy()
println("MYSERVICE override fun onDestroy() {")
}
}
your Service will start only when BOOT_COMPLETED action will be received, so only when app already installed and system restarts. it won't start when you just install app through adb (as you configure to start Nothing when installed)
make some Activity fully transparent with startService in onCreate and just after that finish() call. include <activity declaration in manifest, but without any <intent-filter. then instead of Nothing to run when app install just pick Specified Activity and point on this transparent one, which starts Service and quits after that. without intent-filter Activity won't be visible in launcher and only way to start it will be your configuration in AS
when you will be sending your app to end-users then remove <activity declaration leaving no actual way to run this transparent Activity. only Service can be started then, in current circumstances only when system boots up
btw. your Nothing link assumes your app will be system-belong, moved to system partition/folder. do you have such privileges? (on usual user device this won't be possible, you need root privileges) without that all red-marked lines in <application tag won't work
edit:
step 1:
create file res/values/styles.xml and past below or if present already add below <style tag
<resources>
<style name="Theme.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
step 2: create new Activity and declare in manifest with above style
<activity android:name=".YourActivity" android:theme="#style/Theme.Transparent"/>
if you add below <intent-filter to <activity tag then this Activity shows in system UI (launcher), so just don't do that, placing here just to inform
// launcher icon declaration, not for OPs case
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN"/>
// MAIN must be placed with first LAUNCHER declaration
</intent-filter>
note that you can also create multiple <activity tags with LAUNCHER declaration (second and further without MAIN tag), making your app show multiple icons, one per Activity LAUNCHER-declared (you can also change their names and icons as far as I remember)
step 3: inside onCreate just after super.onCreate call start your Service and then quit this invisible Activity
startService(this, MyService.class); // will start service
finish(); // quits activity
step 4: under Edit Configurations... instead of Nothing just pick Specified Activity
I have my application that allows other apps that can share files to select it on the share menu, open the application up and "transfer" the files over to my app.
My problem is when they select my application from the share menu (as example, in gallery, after selecting several photos, they choose to share with my app) the login activity gets opened inside the gallery application
Please note that i have tried this process works on older devices and it worked but not for a newer device.
This is my manifest.xml
<application
android:name="com.Application"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:mimeType="*/*"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan"/>
<activity
android:name=".login.LoginActivity"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize|stateVisible">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
I have two activities for this app, login and Main, Main will be loaded up if login is successful.
I have tried with different kinds of launcherMode settings but nothing has stopped the instance from being created in gallery
This is from my login Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
receivedIntent = getIntent();
//set orientation
setRequestedOrientation(isPhone() ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null && intent.getAction() != null && (intent.getAction().equals(Intent.ACTION_SEND) || intent.getAction().equals(Intent.ACTION_SEND_MULTIPLE))){
finish();
startActivity(intent);
}
}
The problem is, on the older device the onNewIntent method gets called as expected, but on the newer device it just ignores the launcherMode and creates the new instance and runs onCreate()
Any ideas on how to get the application to "force" launch itself when called from a share menu?
Current Testing devices - Samsung mobile Android 8.0, API 26 - not working
Samsung Tablet Android 7.1.1, API 25 - working as expected
All your issue is about the permissions,
Old devices below kitkat(4.4.2) does not required permissions of file but in new devices required permissions for access the file data(ie. gallery and others).
You have to grant permission programmatically,
if (Build.VERSION.SDK_INT > 19) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
arrPerm.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!arrPerm.isEmpty()) {
String[] permissions = new String[arrPerm.size()];
permissions = arrPerm.toArray(permissions);
ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST);
}
}
After Permission Granted you can do your operation:
if (Build.VERSION.SDK_INT > 19) {
if (isPermissionGranted()) {
//Do your Task of gallery
}
}
Or alternate way, you can use library directly:
https://github.com/nabinbhandari/Android-Permissions
I did some digging into other apps on the device and found this issue is only occurring when sharing images from the application "Gallery" otherwise the code works as expected, so i believe this could be an issue with Gallery itself or is expected behavior for the Gallery application.
I'm hoping one of you fine folk may be able to help me out with a little issue I am having whilst using Android Intent.createChooser(). I am learning as I go with my application so I apologise if I have the wrong end of the stick with how this should work!
I have been following a number of tutorials and have implemented some code which starts an Intent.createChooser() to share a picture to social media. The code that I have used works fine in that I am able to share the picture as I intended, my issue is that when the code is run my main activity (or any activity I call the code from) appears to close and the chooser appears in front of the homescreen or any other applications I may have open. The effect that I was hoping to have, and the one which seemed to be apparent in the tutorials, is for the chooser to appear in front of the running activity (eg as it does for the gallery).
I am using LibGDX meaning that I have had to use an interface to call the android function that executes the chooser code (in my AndroidLauncher java file). The interfaces all work fine but I wasn't sure if that may have a bearing on the way in which this code operates. I have also played around with swapping to a new activity to implement the chooser code, which I had moved from the AndroidLauncher. This had the same end result.
Any advice on how to make the chooser appear in front of my application would be greatly appreciated! The code which implements the createChooser is included below:
public void ShareHandler(){
String type = "image/*";
String mediaPath = Environment.getExternalStorageDirectory().getPath()+"/Smile.png";
createShareIntent(type, mediaPath);
}
private void createShareIntent(String type, String mediaPath)
{
Intent share = new Intent(Intent.ACTION_SEND);
share.setType(type);
File media = new File(mediaPath);
Uri uri = Uri.fromFile(media);
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Share to"));
}
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.game"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/GdxTheme">
<activity
android:name=".AndroidLauncher"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
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>
<activity android:name=".FacebookServiceHandler" />
<meta-data
android:name="come.facebook.sdk.ApplicationID"
android:value="#string/facebook_app_id" />
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProviderxxxxxxxxxxxxx"
android:exported="true" />
</application>
</manifest>
Thanks in advance, Ben.
If
android:name=".FacebookServiceHandler"
is the activity, that handle the social media sharing of the picture, i would expand that to something like this:
<activity
android:name=".FacebookServiceHandler">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".AndroidLauncher">
</meta-data>
</activity>
This will tell the programm, that the AndroidLauncher is the parentactivity and should make it appear in front of your activity.
Thank you for the suggestions, I have now solved my issue. It turned out that my code was working correctly all along and the issue I was experiencing was as a result of an exit statement within my Core (LibGDX) java code. Essentially when the startActivity(Intent.createChooser(...)) was called, a dispose function within my core files was also being called. This dispose function contained the exit command and was causing the application to finish.
Ugh, so many posts on StackOverflow similar to my problem but none fix it :/
I am currently learning android development. In my main activity I do:
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()){
case R.id.changeName:
Intent intent = new Intent(this, PreferenceActivity.class);
startActivityForResult(intent, 1);
return true;
}
return false;
}
Preference.java is a freshly created activity with nothing in it except the automatically created onCreate method. The error is:
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.package.chat.oneway.client/android.preference.PreferenceActivity}; have you declared this activity in your AndroidManifest.xml?
My android manifest has:
<application
android:allowBackup="false"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name=".ChatClient"
android:label="#string/app_name" />
<activity android:name=".Parent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PreferenceActivity"></activity>
</application>
As you can see, .PreferenceActivity is in the manifest. The packages for the ChatClient and PreferenceActivity activities are the same com.package.chat.oneway.client package.It's been driving me nuts for the past 4 hours.
As you can see, .PreferenceActivity is in the manifest.
Yes, it is. However, that is not what your Intent is using. If you look more closely at the error message, you will see that your Intent is using android.preference.PreferenceActivity.
This comes when you reuse existing class names. There are countless possible class names. Rename yours to something else, and you can avoid this sort of problem in the future.
Or, if you are completely set on having your class named PreferenceActivity, then remove the import android.preference.PreferenceActivity statement from the class where you are creating your Intent. Or, change your Intent to:
Intent intent = new Intent(this, com.package.chat.oneway.client.PreferenceActivity.class);
I have added my Android app to the "Share-Via" window. Following code is added to the onCreate() method of my code.
if(getIntent().getAction().equals(Intent.ACTION_SEND))
{
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
textField.setText(text);
}
Now the issues is, if this app activity get called from the share-via, it works. But if it get called directly (user opens the app -> go to that activity) this crashes with NullPointerException. I am getting NullPointerException right in here
if(getIntent().getAction().equals(Intent.ACTION_SEND))
Following is how this Share-Via configured in the manifest file.
<activity
android:name="com.xx.xx.xx"
android:screenOrientation="portrait"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
What is the issue here?
Either getIntent() or getAction() is returning null.
You need to check for that.