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.
Related
So let's say I wanna make an app that scans an nfc tag when the user taps the "scan tag" button.
Currently I am having a few issues with it even though I spent the last week trying to figure it out on my own😅
The main issue that I am facing is that the app will scan nfc tags in the background (or at least looks like it) and will open a new instance of my app but with the name of "Nfc Service" (which is not what I named my app).
The other issue that I am facing is that, in the code, when I try to call my "readTag()" mehtod, it only works if it opens that "Nfc Service" thing I said before, otherwise it doesn't read the tag, but only breaks. From my understanding it looks like the readTag() method is running in the background rather than when I tell it to.
TL;DR: I don't want my app to scan nfc tags in the background but only on a button press.
Help would be massively appreciated especially because my deadline it tomorrow 😅 T-T
Here is some of my code (I can't show everything unfortunately):
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ips.software.iasset_ips">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<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.IAssetIPS">
<activity android:name=".WebViews.AssetInfoWebView"></activity>
<activity android:name=".Activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
</application>
</manifest>
xml/nfc_tech_filter:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
</resources>
MainActivity: (just the parts relevant to the question)
// package + all the imports
// ...
public class MainActivity extends AppCompatActivity {
private Button scanButton;
NfcAdapter adapter;
Tag tag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
configureScanButton();
}
private void configureScanButton() {
scanButton= findViewById(R.id.scanButton);
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
readTag();
}
});
}
public void readTag() {
adapter = NfcAdapter.getDefaultAdapter(this); // initialize the nfc reader
checkNfcSupport(); // check if device supports nfc, if not close and Toast.show
tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); // read the tag
decodeSerialNumberFromTag(); // can't show you this function, but it's only decoding, it shouldn't be the cause of the problem
Toast.makeText(this, "Serial Number: " + serialNumber, Toast.LENGTH_LONG).show();
}
}
So yeah i think that's all, it would also be nice if I could call the readTag() method whenever I want to scan a new tag.
I talk too much, thank you in advance :D
The only way to start the interaction of you App to an NFC Tag is via the NFC Service, but if you program it properly it is possible to achieve the your desired behaviour.
First off, the manifest Intent filter are really only about telling the NFC Service to start/restart your App when a Tag of the right type comes in to range.
There is an interaction with the "launchMode" of your App as detailed in https://stackoverflow.com/a/64834600/2373819
The way to handle an NFC tag when your App is running is to use enableForegroundDispatch or use the better enableReaderMode APIs which tell the NFC Service to pass you the Tag object in different ways when a Tag comes in to range.
An example of the better enableReaderMode API for reading and writing is at https://stackoverflow.com/a/64921434/2373819 (You can ignore the writing bit)
It is not the normal workflow to do something with a Tag only when you press a button as a Tag might or might not be in range, what you are actually doing in your current readTag method when you press the button is just processing the Intent that was stored when the activity was started no actually I/O for reading is being done to the Tag. The Tag UID and any NDEF message stored on the Tag will have been cached in the Tag Object/Intent when it came in to range.
To do the similar with enableReaderMode in the onTagDiscovered method you would store the Tag Object is a global variable in the Activity class and then process it when you press the button with checking the Tag object is not null i.e. user has pressed the button with not Tag has every been in range.
If want to read other non cached data when you press the button you need to handle Tag out or range errors and other I/O errors as you would if your were processing the Tag immediately when it came in to range, just you are more likely to have them.
I would say it is always good practise when using NFC in your App to enableForegroundDispatch or use the better enableReaderMode to as the NFC service to send you the Tag Object even if you don't want to do anything with it at that point in time because it will prevent the NFC service launching another App to handle it or even itself displaying a basic information screen over the top of your App about the Tag that came in to range. e.g. have an empty method in onNewIntent or onTagDiscovered
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
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 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>.
I have a game application made up of several different activities. The first to be called is a splash screen, when this completes, this finishes and starts up another activity via an intent. In order to have access to some global data that is consistent across all the activities, I also have a "globals" class like this:
public class Globals extends Application
{
int global_variable_A;
int global_variable_B;
int global_variable_C;
public void onCreate()
{
// stuff
}
}
In the androidmanifest.xml I have the the following (amongst other things):
<application
android:icon="#drawable/mygame_icon"
android:screenOrientation="portrait"
android:label='"My Game"' android:name=".Globals">
<activity
android:label="My Game"
android:name=".Splash"
android:screenOrientation="portrait">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
My question now is, which will be executed first, the onCreate of Globals or the onCreate of Splash? Or are they run at the same time on different threads? I ask because I'm getting some inconsistent behaviour that would be explained if they were on different threads.
onCreate() Global off course.. Application gets executed first and then the Activity,,.. you can test for yourself by keeping a debug point in Application onCreate() method..