is it possible to start reading from a nfc-chip after pressing a button. After pushing the button there should be a message like "please hold your nfc chip close to the device..". I only see tutorials, which show how to start the application when holding a nfc chip to the device (onNewIntent).
Second Question. What if the application is already running and i hold the nfc chip next to my device? Is it forcing a destroy and then launches again?
Thanks!
Regarding the first part of your question, you could use a flag within your activity that indicates the state of your application (ready to write/message is showing, not ready to write/message not showing). YOu can find a simple example here:
private static final int DIALOG_WRITE = 1;
private boolean mWrite = false; // write state
public void onCreate(Bundle savedInstanceState) {
[...]
// Set action for "Write to tag..." button:
mMyWriteButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Switch to write mode:
mWrite = true;
// Show a dialog when we are ready to write:
showDialog(DIALOG_WRITE);
}
});
[...]
}
protected Dialog onCreateDialog(int id, Bundle args) {
switch (id) {
case DIALOG_WRITE:
// A dialog that we show when we are ready to write to a tag:
return new AlertDialog.Builder(this)
.setTitle("Write to tag...")
.setMessage("Touch tag to start writing.")
.setCancelable(true)
.setNeutralButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface d, int arg) {
d.cancel();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface d) {
mWrite = false;
}
}).create();
}
return null;
}
// You would call this method from onCreate/onStart/onResume/onNewIntent
// or from whereever you want to process an incoming intent
private void resolveIntent(Intent data, boolean foregroundDispatch) {
String action = data.getAction();
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
// The reference to the tag that invoked us is passed as a parameter (intent extra EXTRA_TAG)
Tag tag = data.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (mWrite) {
// We want to write
mWrite = false;
// TODO: write to tag
} else {
// not in write-mode
// TODO: read tag or do nothing
}
}
}
Regarding the second part of your question, when you want to receive NFC tag discovery events while your activity is already in the foreground, you should register with the NFC foreground dispatch system. See Advanced NFC: Using the NFC Foreground Dispatch System. There is no need to destroy and re-create your activity.
Related
I'm using nearby connections to create a connection between devices. When a connection has been established, the activity is changed. Now if a device disconnects then a callback is called, but its received in the old activity. Now I want to show an AlertDialog, but the dialog is never shown because it shows on the old activity. How can show the dialog on the new activity?
I'm using nearby connections like this: URL
private Activity mActivity;
public RemoteConnection(Activity activity){
mActivity = activity;
}
// For simplicity I did only include this method
#Override
public void onDisconnected(String endpointId) {
// We've been disconnected from this endpoint. No more data can be
// sent or received.
new AlertDialog.Builder(mActivity)
.setTitle("Disconnection")
.setMessage("Other device is disconnected")
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
The dialog should be shown on the current activity
Write a method in your activities as:
public void showAlert(activity)
{
new AlertDialog.Builder(activity)
.setTitle("Disconnection")
.setMessage("Other device is disconnected")
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
and change following code :
#Override
public void onDisconnected(String endpointId) {
// We've been disconnected from this endpoint. No more data can be
// sent or received.
new AlertDialog.Builder(mActivity)
.setTitle("Disconnection")
.setMessage("Other device is disconnected")
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
To:
#Override
public void onDisconnected(String endpointId) {
// We've been disconnected from this endpoint. No more data can be
// sent or received.
if(((YourActivityA)activity) != null)
{
((YourActivityA)activity).showAlert(activity);
}
else if(((YourActivityB)activity) != null)
{
((YourActivityB)activity).showAlert(activity);
}
}
Use an event bus implementation or send the callback using sendBroadcast() and have each Activity register a BroadcastReceiver in onResume() and unregister it in onPause().
In my app i have a function that checks the entered text from a displayed AlertDialog with an input text. If the text is equal to a string variable, return True, else return False, and catch this resulting value to continue conditional code.
But it seems its a little difficult to do this as i've read in other posts asking how to solve the same problem.
I've already done this:
private boolean checkAdministratorPassword() {
final enterPasswordResult[0] = false;
AlertDialog.Builder alert = new AlertDialog.Builder(mContext);
alert.setTitle("Confirm action");
alert.setIcon(R.drawable.ic_launcher);
alert.setMessage("Enter administrator pass to continue");
final EditText input = new EditText(mContext);
input.setPadding(5, 0, 5, 0);
alert.setView(input);
alert.setPositiveButton("Accept", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String strPass = input.getEditableText().toString();
if (strPass.length() == 0) {
dialog.cancel();
}
if (strPass.equalsIgnoreCase(Constantes.ADMIN_PASS)) {
enterPasswordResult[0] = true;
dialog.cancel();
} else {
Toast.makeText(mContext, "Invalid pass..!!", Toast.LENGTH_LONG).show();
dialog.cancel();
}
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
return enterPasswordResult[0];
}
And i call the function this way:
If ( checkAdministratorPassword() == True ){
//true conditions
}
But the problem is that the check function doesnt wait for the result to continue with the code, it just continue by itself and i dont get the appropiate behavior.
The issue is you're trying to handle an async event in the logcal flow of your program. You can do this if you make the Dialog it's own class and use an Interface to callback to your host activity. Check out the documentation on DialogFragment.
public interface PasswordCheckListener{
public void valid(boolean check);
}
private static class PasswordDialog extends DialogFragment {
private PasswordCheckListener listener;
public static PaswordDialog newInstance(PasswordCheckListener listener){
this.listener = listener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//Put your dialog creation code here
}
private checkAdminPassword(){
//Whatever your check passowrd code is
listener.valid(result);
}
}
I realize I didn't implement all the code for you but that's the general idea. By using an interface you can call back to your host Activity or Fragment when the user enters the password and presses submit. You can then handle the event as it happens, rather than having to deal with it in your program flow.
Thank you all for your answers!! i've found the right way to achieve this problem by creating an Activity whith theme "Theme.Dialog", an input text and two buttons (Accept, Cancel), i start this activity for result asking the user to enter the administrator pass to continue, checking the string and then returning again to onActivityResult() from previous activity with the correct information to proceed.
I have an android app using P2P NFC. NFC works but i have to tap the devices twice to start it. When i debug my app and tap devices it calls createNdefMessage function but throws an exception at JavaBinder.
In run mode it doesn't crashes but i have to tap the devices twice to start NFC.
Before NFC i call a file selector to select a file to transfer.
Here is my code OnCreate
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// INFO TEXTVIEW
mInfoText = (TextView) findViewById(R.id.info_text_view);
// FILE SELECTOR BUTTON
mStartActivityButton = (Button)findViewById(R.id.start_file_picker_button);
mStartActivityButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.start_file_picker_button:
// Create a new Intent for the file picker activity
Intent intent = new Intent(getApplicationContext(), FilePickerActivity.class);
// Start the activity
startActivityForResult(intent, REQUEST_PICK_FILE);
break;
}
}
});
// CHECK FOR AVAILABLE NFC ADAPTOR
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
mInfoText.setText("NFC is not available on this device.");
} else {
// Register callback to set NDEF message
mNfcAdapter.setNdefPushMessageCallback(this, this);
// Register callback to listen for message-sent success
mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
}
createNdefMessage
public NdefMessage createNdefMessage(NfcEvent event) {
Time time = new Time();
time.setToNow();
mInfoText.setTextColor(Color.WHITE);
mInfoText.setText("File Transfer In Progress ...");
NdefMessage msg = new NdefMessage(NdefRecord.createMime(
"application/com.example.android.beam", text.getBytes()));
return msg;
}
My app throughs an exception at
mInfoText.setTextColor(Color.WHITE);
Is it because i am having two intents?
I think that when you call mInfoText.setTextColor(Color.WHITE) mInfoText is null. Try initialising with findViewById() before you call setTextColor
In my chat application i want that when the person is not on the chat screen then he should receive the notifications and when the person is not on the chat screen then he should not receive any notifications ( chat should be simply displayed on the chat screen itself).
When the person is on the chat screen, I forcefully change the status the of the user and broadcast it. Now here the problem is that when the user will receive any msg/chat now how will the service running on the user's device will decide the presence of the mobile user itself ( i.e is he is on the chat screen or not ). I think it is not possible to get the presence of the user itself ( with help of roster as the user itself is not listed in his roster)
this function is written in my service class
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
final PacketCollector collector = connection.createPacketCollector(filter);
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
// TODO Auto-generated method stub
//notification(packet.getFrom());
packet = collector.nextResult();
Message message = (Message)packet;
senderName = packet.getFrom();
int alphaPOS = senderName.indexOf("#");
String subSenderName = senderName.substring(0,alphaPOS);
notificationforChat(subSenderName+": "+message.getBody(),packet.getFrom().toString());
}
}, filter);
Now how to stop the notifications when the user is on the chat screen itself???
Please help me
In your activity write this method.
public static boolean isVisible = false;
#Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
if(hasFocus)
{
isVisible = true;
}
else
{
isVisible = false;
}
}
and wherever you wish use this boolean to check that is screen visible or not.
Is your chat screen embedded in an android activity? If so, you can override your Activity's onResume() and onPause() methods to set some sort of a flag, so that your service would now if the activity is being active(when the user is using it) or if it is not visible. One way to do this is to use shared preferences. Here's a simplified outline:
#Override
public void onResume() {
setUserPresence(true);
super.onResume();
}
#Override
public void onPause() {
setUserPresence(false);
super.onResume()
}
public void setUserPresence(boolean state) {
SharedPreferences prefs = getSharedPreferences("settings_file_name",MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("UserPresent", state);
editor.commit(); //Save your settings to the shared preferences file
}
And then all you need to do is check this flag in your service, using the same SharedPreferences approach.
I am developing a Bluetooth chat application with the help of the Bluetooth chat application on the Android developer site.
I did some modifications in existing code as when I send Bluetooth chat requests to another device (assume we are paired previously) and request receiving device resides in any activity.
I want to display an alert to the current displaying screen, but I am getting an alert at a particular activity only. So I am getting stuck. My code is below for the sender and receiver side:
if (FaceCardList.requestConnection &&
FaceCardList.deviceSelected) {
String authorization = "messagetype:startChat,"
+ FaceCardList.ScreenName;
FaceCardList.this.sendMessage(authorization);
}
On the receiving side:
if (readMessage.indexOf("messagetype:startChat") != -1) {
AlertDialog.Builder builder =
new AlertDialog.Builder(FaceCardList.this);
builder.setMessage(
FaceCardList.screennmname + " wants to chat with you")
.setCancelable(false)
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
Intent serverIntent = new Intent(
FaceCardList.this,
BluetoothChat.class);
startActivity(serverIntent);
String authorization = "messagetype:initiatechat";
FaceCardList.this
.sendMessage(authorization);
}
})
.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface diaLog,
int which) {
// TODO Auto-generated method stub
String authorization = "messagetype:stopservice";
FaceCardList.this
.sendMessage(authorization);
FaceCardList.mChatService.stop();
FaceCardList.mChatService.start();
}
});
alert = builder.create();
alert.show();
If you have one central communication activity which is receiving requests you may just use a Handler to communicate with any other activity easily.
See here for reference:http://developer.android.com/reference/android/os/Handler.html
There are many tutorials and examples.
Using handlers is extremely easy and yet flexible - it does not block your activity but allows any kind of communication, even passing parameters
You may create a central communicator class with static methods and send all your requests via this central point to dispatch to whatever activity you like depending on a defined logic within this one point.
Here an example for such a method with parameters:
static public void sendMessageToDialogDuringChat(
int msgID, String msgText, boolean statusBool) {
if (theHandlerForScreenUpdate == null) // you need to create the receiving handler within this class beforehand
return;
Message msgForDialogDuringChat= theHandlerForScreenUpdate
.obtainMessage(msgID);
Bundle bundle = new Bundle();
bundle.putBoolean(msgText, statusBool);
msgForDialogDuringChat.setData(bundle);
theHandlerForScreenUpdate
.sendMessage(msgForDialogDuringChat);
}
and here a handler to receive the message. Be sure that within the central dispatcher you have stored the appropriate handler which should receive the message.
public final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
"-> "
+ Thread.currentThread().getStackTrace()[2]
.getMethodName() + " msg.what="
+ msg.what);
switch (msg.what) {
case MESSAGE_CONNECTION_SUCCESSFULL_FLAG: {
boolean connectionOK = msg.getData().getBoolean(
CONNECTION_SUCCESS);
if (connectionOK)
theStatusTV
.setText(getString(R.string.connection_OK));
else {
theStatusTV
.setText(getString(R.string.connection_NOT_OK));
}
}
break;
case MESSAGE_ALERT_FLAG: {
...start your alert here...
Certainly you could do all of that in the receiving class as well - depends how you need to structure your "special" communication messages