Could someone explain the following lines in the manifest -
<activity
android:name=".AboutUs"
android:label="#string/app_name">
<intent-filter >
<action android:name="com.example.app1.ABOUT" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
How are the fields in activity and intent filter important and when are they used/referred ?
Sorry, i tried to read the documentation but still couldnt figure much out.
Thank you
android:name=".AboutUs"
This is the name of your Activity class, the dot at the front is shorthand notation for your package. So this actually stands for com.your.package.name.AboutUs which means your java file that represents this Activity is called AboutUs.java
android:label="#string/app_name"
label is the string that gets shown in the launcher(if the activity is listed in the launcher) and at the top of the window when the activity is open.
<intent-filter > ... </intent-filter>
intent filter defines the Intents that your activity "listens for" in order to launch.
<action android:name="com.example.app1.ABOUT" />
<category android:name="android.intent.category.DEFAULT"/>
Action and category are both fields that get set on an Intent before it is "fired off" into the system. The system will then look for any activities that match both the action and category and if it finds one then it will launch that activity, or if it finds multiple it will show the user all of them and let them pick.
In your case your the action you are listening for com.example.app1.ABOUT is a custom action that is specific to your app, not one of the systems actions.
So here is what an intent that would start this particular activity might look like:
Intent i = new Intent();
i.setAction("com.example.app1.ABOUT");
i.addCategory("android.intent.category.DEFAULT");
startActivity(i);
Note that because you've created a custom action, this intent does not require access to your AboutUs.class so this intent could technically be fired from any app on the device and it would launch into your activity.
For the ACTION you have this answer and for the DEFAULT category you have this answer
An Activity is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. To declare your activity, open your manifest file and add an element as a child of the element like your example.
The android:name attribute is the only required attribute—it specifies the class name of the activity.
The android:label attribute is a user-readable label for the application as a whole, and a default label for each of the application's components
An element can also specify various intent filters—using the element—in order to declare how other application components may activate it.
The element specifies that this is the "main" entry point to the application.
The element specifies that this activity should be listed in the system's application launcher (to allow users to launch this activity).
Please refer to the http://developer.android.com/guide/components/activities.html
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
My first App
This is my first android app - QR Code Scanner using ZXingScanner Library.
Is there any way to launch a new screen (activity) instead of replacing the crurent one, so i can press back from the scanner to go back to main screen where is the button?
Please help me. Thanks all
I think that this site can help you: http://developer.android.com/training/basics/firstapp/starting-activity.html
In short words:
You need to create new
Intent myIntent = new Intent(this, SecondActivity.class) and than start it by startActivity(myIntent).
Additionally it will be good to define your MAIN activity in AndroidManifest.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
You should create 2 activities in your app.
From first activity send an intent to the second activity that you created before (I think that you can create one). With sending an intent to another activity the first one remain, and you can use back button to load that.
Now this is the easiest way that you can send an intent:
Intent intent= new Intent(Activity1.this,Activity2.class);
startActivity(intent);
But there is some other ways to send an activity(similar to this one):
How to start new activity on button click
I want to add a feature to my app that when I touch the number in a message, the user can decide to send the number to my app or Android Dialer.
For example my friend send me a code and i want to use this code for special ussd code that my app run it.
I think I have to use implicit intent but I don't know how?
Thanks
I have quoted the below links
-intent filter
-Intents implicit\explicit
Implicit intents specify the action which should be performed and
optionally data which provides data for the action.
For example the following tells the Android system to view a webpage.
All installed web browsers should be registered to the corresponding
intent data via an intent filter.
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.vogella.com")); startActivity(i);
If an Explicit intent is send to the Android system, it searches for all
components which are registered for the specific action and the
fitting data type.
If only one component is found, Android starts this component
directly. If several components are identifier by the Android system,
the user will get an selection dialog and can decide which component
should be used for the intent.
How to use
You can register your own components via Intent filters. If a
component does not define one, it can only be called by explicit
intent.
Register an activity as Browser
<activity android:name=".BrowserActivitiy"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
UPDATES
A code sample for mimeType
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*"/>
</intent-filter>
I assume you are talking about a number in a SMS that you received. On clicking that number you want the user to get an option to either dial or use your app.
If yes then you need to include intent filter in your manifest file for launcher activity.
If Android Application Record (AAR) is used, intent action is
android.intent.action.MAIN
So I can not know if this is normal launch or nfc launch.
I need to do slighty different things in my activity whether activity is launched normally or after nfc tag reading. I also dont want to show prompt for choosing app if there is another app on the phone with the same intent filter, e.g.:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
If you put the AAR not as the first record of the NDEF message (so 2nd record or later) and you put an NDEF_DISCOVERED intent filter in the manifest for the first record of the NDEF message, your app will get an NDEF_DISCOVERED intent when launched from a tag. The intent will have EXTRAs containing a handle to the tag and the complete NDEF message.
If the AAR is the first record, an ACTION_MAIN intent will be sent to the app. This intent will not contain any tag or NDEF message in the EXTRAs.
To prevent your app from showing up when scanning other NFC tags, make sure that the first NDEF record has a type that is unique to your app and filter for that. The External Type was specifically designed for this purpose. (Due to the AAR in your tag, no other apps will show up when you scan it.)
[Edit]:
Check for payload in your intent: EXTRA_TAG or EXTRA_NDEF_MESSAGES
This extra will always be set if the intent comes from an NFC event.
[obsolete]:
Use
getIntent()
and check its
action
Lets say I launch my app from the home screen, navigate through some activities, then I press the home key and do something else in the Gmail app.
After i'm done checking my mail,I press the home key again to leave the Gmail app and click my app's icon at the home screen again to return to it.
When I return to my app, I want it to return to the last activity I was at, NOT start a whole new session. I've been trying to figure this out all day.
My manifest for my first activity is as follows:
<activity android:name=".Main"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:alwaysRetainTaskState="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The category attribute LAUNCHER makes my app ALWAYS start at activity Main, so I don't know how to go about restoring the last activity. People have told me to use sharedpreferences to save the last activity and load it on Launch, but I don't think it's intended to be done that way because it isn't very elegant.
I think its the only way because what happens when you're launching an app is that Launcher application sends intent "android.intent.action.MAIN" And the only activity in your app that responds to this intent is your main activity, thus it gets activated. So the only thing you can do is save somewhere your session and on activity start up if there's already saved session restore the app to the previous state.
Try using one of these in your manifest :
<activity android:launchMode=["multiple" | "singleTop" |
"singleTask" | "singleInstance"] ...
Are onResume() and onPause implemented properly?
protected void onResume(){
super.onResume();
}
protected void onPause() {
super.onPause();
}