I'm trying to implement complication support for my watch. Here's my AndroidManifest.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wearapp">
<uses-feature android:name="android.hardware.type.watch"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<!-- Watch Face -->
<service
android:name=".ComplicationSimpleWatchFaceService"
android:enabled="true"
android:label="Fancy Watch"
android:permission="android.permission.BIND_WALLPAPER">
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/watch_face"/>
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="#drawable/preview_complication_simple"/>
<meta-data
android:name="com.google.android.wearable.watchface.preview_circular"
android:resource="#drawable/preview_complication_simple"/>
<meta-data
android:name="com.google.android.wearable.watchface.wearableConfigurationAction"
android:value="com.example.wearapp.CONFIG_COMPLICATION_SIMPLE"/>
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService"/>
<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE"/>
</intent-filter>
</service>
<activity android:name="android.support.wearable.complications.ComplicationHelperActivity"/>
<activity
android:name=".ComplicationSimpleConfigActivity"
android:label="Fancy Watch">
<intent-filter>
<action android:name="com.example.wearapp.CONFIG_COMPLICATION_SIMPLE"/>
<category android:name="com.google.android.wearable.watchface.category.WEARABLE_CONFIGURATION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
I have a watch face service and a config activity. When I use ComplicationHelperActivity to createProviderChooserHelperIntent from the config activity I always get result cancelled in the onActivityResult. Here's how I start chooser activity and listen for the result
#Override
public void onClick(WearableListView.ViewHolder viewHolder) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onClick()");
}
Integer tag = (Integer) viewHolder.itemView.getTag();
ComplicationItem complicationItem = mAdapter.getItem(tag);
startActivityForResult(ComplicationHelperActivity.createProviderChooserHelperIntent(
getApplicationContext(),
complicationItem.watchFace,
complicationItem.complicationId,
complicationItem.supportedTypes),
PROVIDER_CHOOSER_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PROVIDER_CHOOSER_REQUEST_CODE
&& resultCode == RESULT_OK) {
ComplicationProviderInfo complicationProviderInfo =
data.getParcelableExtra(ProviderChooserIntent.EXTRA_PROVIDER_INFO);
Log.d(TAG, "Selected Provider: " + complicationProviderInfo);
finish();
}
}
It seems like I'm missing complication support and that's why can't choose any provider. But to test this I copied ComplicationSimpleWatchFaceService from the WatchFace sample and still don't have any result. Here's complication code from the watch face.
private static final int LEFT_DIAL_COMPLICATION = 0;
private static final int RIGHT_DIAL_COMPLICATION = 1;
public static final int[] COMPLICATION_IDS = {LEFT_DIAL_COMPLICATION, RIGHT_DIAL_COMPLICATION};
public static final int[][] COMPLICATION_SUPPORTED_TYPES = {
{ComplicationData.TYPE_SHORT_TEXT},
{ComplicationData.TYPE_SHORT_TEXT}
};
private void initializeComplication() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "initializeComplications()");
}
mActiveComplicationDataSparseArray = new SparseArray<>(COMPLICATION_IDS.length);
mComplicationPaint = new Paint();
mComplicationPaint.setColor(Color.WHITE);
mComplicationPaint.setTextSize(COMPLICATION_TEXT_SIZE);
mComplicationPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
mComplicationPaint.setAntiAlias(true);
setActiveComplications(COMPLICATION_IDS);
}
Make sure that you have called the ComplicationHelperActivity.createProviderChooserHelperIntent method, to obtain an intent and to start the provider chooser.
Sample code (make sure to call the getActivity() method for it to launch):
startActivityForResult(
ComplicationHelperActivity.createProviderChooserHelperIntent(
getActivity(),
watchFace,
complicationId,
ComplicationData.TYPE_LARGE_IMAGE),
PROVIDER_CHOOSER_REQUEST_CODE);
The intent can be used with either startActivity or startActivityForResult to launch the chooser.
You can followed this tutorial and see if you missed some configurations.
Related
I need help or guidance in resolving the issue that I have regarding React Native interacting with other native applications via intents. I know that React Native supports deeplinking out of the box but does not cater for intents, which means that one needs to create an android native module (https://reactnative.dev/docs/native-modules-android). I created a native module that calls 3rd party applications via intents and passing data using startActivityForResults and created onActivityResult that is supposed to handle data returned from 3rd party applications after closing. However, the onActivityResult executes prematurely before external applications open.
Starting the activity using startActivityForResults:
#ReactMethod
public void launchApp(String stringArgument, ReadableMap args, Promise promise) throws JSONException{
try {
final JSONObject options = convertMapToJson(args);
Bundle extras = new Bundle();;
int LAUNCH_REQUEST = 0;
if (options.has("extras")) {
extras = createExtras(options.getJSONArray("extras"));
Log.d(TAG,"Extras found");
Log.d(TAG, options.getString("extras"));
} else {
extras = new Bundle();
Log.d(TAG,"No extras");
}
if (options.has("launchRequestCode")) {
LAUNCH_REQUEST = options.getInt("launchRequestCode");
}
Intent packageIntent = this.reactContext.getPackageManager().getLaunchIntentForPackage(stringArgument);
if(packageIntent != null){
packageIntent.putExtras(extras);
//callback.invoke("Starting activity for: "+stringArgument);
Activity activity = getReactApplicationContext().getCurrentActivity();
//this.reactContext.startActivityForResult(packageIntent, LAUNCH_REQUEST, extras);
activity.startActivityForResult(packageIntent, LAUNCH_REQUEST);
return;
//mPromise.put(LAUNCH_REQUEST, promise);
}
else{
Log.d(TAG, stringArgument+" package not found");
//callback.invoke("Package not found: "+stringArgument);
}
} catch (JSONException e) {
//TODO: handle exception
Log.d(TAG, e.toString());
}
// TODO: Implement some actually useful functionality
}
Expecting the data back using onActivityResults
ActivityEventListener mActivityEventListener = new ActivityEventListener(){
#Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resCode, data);
Log.d(TAG,"On activity result");
if (mPromise != null && resultCode == activity.RESULT_OK) {
WritableMap result = new WritableNativeMap();
result.putInt("resultCode", resultCode);
result.putMap("data", Arguments.makeNativeMap(data.getExtras()));
mPromise.resolve(result);
}
else{
Log.d(TAG,"Promise and intent data are empty");
//mPromise.reject("Unable to get promise or intent data is empty");
}
if(resultCode == activity.RESULT_CANCELED ){
Log.d(TAG,"Result cancelled or no result or crashed with code");
}
}
#Override
public void onNewIntent(Intent intent){
Log.d(TAG,"New Intent");
}
};
Android Manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.navapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
By using Android Studio Logcat to debug, I found out that the onActivityResults executes immediately before the external app opens up.
Logcat screenshot
Thanks to this explanation here, I was able to drill down to what was causing the issue. In my React Native application, I used the package name of the external application instead of the action name to open it.
Manifest File of the external app:
<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/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTask"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.bld.pushnotification.Main"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
I also modified the my code for launching the app:
#ReactMethod
public void launchApp(String stringArgument, ReadableMap args, Promise promise) throws JSONException{
try {
final JSONObject options = convertMapToJson(args);
Bundle extras = new Bundle();;
int LAUNCH_REQUEST = 0;
if (options.has("extras")) {
extras = createExtras(options.getJSONArray("extras"));
Log.d(TAG,"Extras found");
Log.d(TAG, options.getString("extras"));
} else {
extras = new Bundle();
Log.d(TAG,"No extras");
}
if (options.has("launchRequestCode")) {
LAUNCH_REQUEST = options.getInt("launchRequestCode");
}
Intent packageIntent = new Intent(stringArgument);
Activity activity = getReactApplicationContext().getCurrentActivity();
activity.startActivityForResult(packageIntent, LAUNCH_REQUEST);
} catch (JSONException e) {
//TODO: handle exception
Log.d(TAG, e.toString());
}
}
I am using the PayPal mobile SDK (Android) because I need access to the REST API, and I am using the Sandbox. Immediate payments work fine, but I can't get an authorization code for future payments. I have checked the developer portal and future payments are enabled, although I think this is the default for the Sandbox anyway. I am using Xamarin android (c#):
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="ShoezApp.Android">
<!--This will default to ShoezApp.ShoezApp if no second part is specified-->
<uses-sdk android:minSdkVersion="19" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- admob permissions-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="ShoezApp" android:icon="#drawable/icon">
<activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity" android:launchMode="singleTop" android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="shoezapp" android:host="easyauth.callback" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version"/>
<activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="#android:style/Theme.Translucent" />
</application>
</manifest>
Code:
public class PayPalDroid : IPayPalService
{
private PayPalConfiguration config = new PayPalConfiguration()
.Environment(PayPalConfiguration.EnvironmentSandbox)
.ClientId("AeX06w97L702sEFGK5ZB4Tc4Veyo4oOzopS9DgKiHCDVgD4O0mGeZoNl1t-sFWAmRXyzyx87Y1mupJ1W")
.MerchantName("Example Merchant")
.MerchantPrivacyPolicyUri(Android.Net.Uri.Parse("https://www.example.com/privacy"))
.MerchantUserAgreementUri(Android.Net.Uri.Parse("https://www.example.com/legal"));
//only calls default constructor with dependency injection, so this is necessary
public PayPalDroid() {}
private int REQUEST_CODE_PAYMENT = 1;
private int REQUEST_CODE_FUTURE_PAYMENT = 2;
private int REQUEST_CODE_PROFILE_SHARING = 3;
public Task<string> RequestPayPal()
{
Context context = MainActivity.Instance;
MainActivity activity = (MainActivity)context;
//create the listener
var listener = new ActivityResultListener(activity);
// start paypal service - this must be done each time
var intent = new Intent(context, typeof(PayPalService));
intent.PutExtra(PayPalService.ExtraPaypalConfiguration, config);
context.StartActivity(Intent.CreateChooser(intent, "Request PayPal transaction"));
var payment = new PayPalPayment(new Java.Math.BigDecimal("2.45"), "USD", "the item",
PayPalPayment.PaymentIntentSale);
intent = new Intent(context, typeof(PaymentActivity));
intent.PutExtra(PayPalService.ExtraPaypalConfiguration, config);
intent.PutExtra(PaymentActivity.ExtraPayment, payment);
activity.StartActivityForResult(Intent.CreateChooser(intent, "PayPal transaction complete"), REQUEST_CODE_FUTURE_PAYMENT);
return listener.Task;
}
private class ActivityResultListener
{
private TaskCompletionSource<string> Complete = new TaskCompletionSource<string>();
public Task<string> Task { get { return this.Complete.Task; } }
MainActivity Activity;
public ActivityResultListener(MainActivity activity)
{
Activity = activity;
// subscribe to activity results
activity.ActivityResult += OnActivityResult;
}
private void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
// unsubscribe from activity results
Activity.ActivityResult -= OnActivityResult;
// process result
if (resultCode == Result.Ok)
{
Object auth = data.GetParcelableExtra(PayPalFuturePaymentActivity.ExtraResultAuthorization);
if (auth != null) //**THIS IS ALWAYS NULL**//
{
try
{
//string authorization_code = auth.AuthorizationCode;
//sendAuthorizationToServer(auth);
}
catch (Exception e)
{
//Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e);
}
}
}
Complete.TrySetResult(resultCode.ToString());
Context context = MainActivity.Instance;
var intent = new Intent(context, typeof(PayPalService));
context.StopService(intent);
}
}
}
I can't go any further (i.e. server side coding) without an authorization code. The problem is the 'auth' object is always null, and I can't see anything wrong with the code as it it basically the sample code. What am I missing? Or does this only work in the live environment?
Thanks.
Made a simple error, the activity needs to be a PayPalFuturePaymentActivity, not a PaymentActivity. A PaymentConfirmation object is available for a PaymentActivity, not a PayPalAuthorization object.
I have found some really good example code for PayPal integration here, which may be helpful to someone else: https://www.csharpcodi.com/vs2/?source=176/PayPal.Forms/MobileApps/PayPal.Forms/PayPalAndroidTest/PayPalManager.cs
Android launch application multiple times on an NFC tag discovered. I tried using the answer in this link Android launch activity multiple times on an NFC tag. but it says resources not found.
I am reading the tag from a fragment. Any help.
This is my manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.atsl.touch">
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<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:supportsRtl="true"
android:launchMode= "singleInstance"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
this is my fragments onResume()
public void onResume() {
super.onResume();
Intent intent =getActivity().getIntent();
pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, 0);
intentFilter = new IntentFilter[] { };
nfcAdapter = NfcAdapter.getDefaultAdapter(getContext());
String action = intent.getAction();
boolean cardMatched=false;
Tag tag=null;
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
Toast.makeText(getContext(),"Blahhhhh",Toast.LENGTH_LONG).show();
tag = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
tappedCard=new Card();
tappedCard.setCardId(MainActivity.bytesToHexString(tag.getId()));
//tag = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
////////////+___________________________________________
////////////+___________________________________________
if(tag == null){
Toast.makeText(getContext(), "tag == null",Toast.LENGTH_SHORT).show();
}else{
Card cc=new Card();
String tagId= MainActivity.bytesToHexString(tag.getId());
cc.setCardId(tagId);
dbHelper=new DBHelper(getContext());
ArrayList<Card> checkList=dbHelper.getAllCards();
if(checkList.size()>0)
{
for(Card d:checkList)
{
if (cc.equals(d))
{
cardMatched=true;
Toast.makeText(getContext(), "Card Matched !!!!",Toast.LENGTH_SHORT).show();
showCardDetails(cc.getCardId());
break;
}
else
{
continue;
}
}
if (!cardMatched)
{
imgBusCard.setVisibility(View.GONE);
showDetails.setVisibility(View.VISIBLE);
Toast.makeText(getContext(), "Card Not Matched !!!!",Toast.LENGTH_SHORT).show();
CustomDialogAddCard customDialogAddCard =new CustomDialogAddCard(getActivity(),"T",cc);
customDialogAddCard.show();
showCardDetails(cc.getCardId());
}
}
else {
Toast.makeText(getContext(), "No cards found !!!!",Toast.LENGTH_SHORT).show();
CustomDialogAddCard customDialogAddCard =new CustomDialogAddCard(getActivity(),"T",cc);
customDialogAddCard.show();
showCardDetails(cc.getCardId());
}
}
}else{
Toast.makeText(getContext(),
"onResume() : " + action,
Toast.LENGTH_SHORT).show();
}
}
The problem is when i run the application and hold an nfc tag near the phone app starts a new instance of the application. it doesn't detect the tag in the initial instance.
This question already has answers here:
How to use NFC ACTIONS
(5 answers)
Closed 3 years ago.
I'm creating application that do some action if hit NFC chip , I know the following information about NFC in Android please correct me if I am wrong
you can't register actions of the NFC to receiver in the manifest file , only activities .
each NFC chip has it's own unique id .
what I want to do is
while the Application is in the background or it's closed , if I hit NFC chip with id (ex 1234) my app lunched and do some action.
is that possible ?
if yes, how it can be achieved?
edit
here is my code , it does open when you check any NFC chip and get this action android.nfc.action.TECH_DISCOVERED
but when it open the action is android.intent.action.MAIN
MainActivity.java
public class MainActivity extends AppCompatActivity {
public static final String ACTION_CHECK_IN= "checked";
public static final String ACTION_CHECK_OUT= "unchecked";
private NfcAdapter mNfcAdapter;
boolean isCheckedIn = false;
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
isCheckedIn = Pref.getBoolean("check", false);
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume() called with: " + "");
String action = getIntent().getAction();
if (action != null) {
Log.d("MainActivity", "onCreate(" + action + ")");
if (action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED) || action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
if (!isCheckedIn) {
isCheckedIn = true;
Pref.putBoolean("check", true);
Log.d("checking","IN");
} else {
isCheckedIn = false;
Pref.putBoolean("check", false);
Log.d("checking","Out");
}
}
}
if (!mNfcAdapter.isEnabled()) {
Toast.makeText(MainActivity.this, "Please open it ", Toast.LENGTH_SHORT).show();
}
/**
* It's important, that the activity is in the foreground.
* Otherwise an IllegalStateException is thrown.
*/
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
/**
* Call this before onPause, otherwise an IllegalArgumentException is thrown.
*/
stopForegroundDispatch(this, mNfcAdapter);
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
public static void setupForegroundDispatch(Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(
activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[2];
String[][] techList = new String[][]{};
// same filter as manifest - action, category
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
filters[1] = new IntentFilter();
filters[1].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
}
manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.srjo.pocnfcadapter">
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/filter_nfc" />
</activity>
</application>
</manifest>
According the the Android Developer site, it is possible for your app to filter NFC intents such as ACTION_NDEF_DISCOVERED.
First register your app in the manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.survivingwithandroid.nfc" >
....
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
<manifest>
Then you should use foreground dispatch (foreground app). Finally you use NFCAdapter to read the content (onNewIntent).
I wrote a detailed posts about NFC if you like give a look.
I am having difficulty getting a BroadcastReceiver to process my IntentService response. The service processes multiple different actions and returns an action type. The receiver will never seem to pick it up, however. The intent does get called as I can debug and set a breakpoint in the IntentService and see the action get processed successfully. I just never see the textbox updated with the appropriate data or see the BroadcastReceiver evein being called.
IntentService
protected void onHandleIntent(Intent intent) {
String action = intent.getAction();
// Data the service was called with.
Bundle incomingData = intent.getExtras();
String key = incomingData.getString(KEY_APPKEY);
String secret = incomingData.getString(KEY_SECRET);
String collection = incomingData.getString(KEY_COLLECTION);
CheckinManager cm = new CheckinManager(this.getApplicationContext(),key,secret,collection);
Intent broadcastIntent = new Intent();
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
if (action == ACTION_GET_POI) {
Double lat = incomingData.getDouble(KEY_LATITUDE);
Double lon = incomingData.getDouble(KEY_LONGITUDE);
ArrayList<POI> nearbyPOIs = new ArrayList<POI>();
//broadcastIntent.setAction(ACTION_GET_POI_PROCESSED);
broadcastIntent.setAction("com.msalinger.checkinmanager.CheckinService.getPOIProcessed");
try {
nearbyPOIs = cm.getPOI(lat, lon);
broadcastIntent.putExtra(OUT_KEY_RESULT, true);
broadcastIntent.putExtra(OUT_KEY_ERROR, "");
broadcastIntent.putParcelableArrayListExtra(OUT_KEY_POILIST, nearbyPOIs);
} catch (JSONException ex) {
Log.d(TAG,ex.getMessage() + "\n" + ex.getStackTrace());
broadcastIntent.putExtra(OUT_KEY_RESULT, false);
broadcastIntent.putExtra(OUT_KEY_ERROR, ex.getMessage());
}
}
else if (action == ACTION_CHECK_IN) {
// Do something
}
else if (action == ACTION_GET_CHECKINS) {
// Do Something
}
else if (action == ACTION_FIND_NEARBY_POIS_WITH_CHECKINS) {
// Do Something
}
sendBroadcast(broadcastIntent);
}
Broadcast Receiver as sub-class of Main Activity
public class CheckinReceiver extends BroadcastReceiver {
private final static String INTENT_BASE_URI = "com.msalinger.checkinmanager.CheckinService";
private final static String ACTION_GET_POI_PROCESSED = ".getPOIProcessed";
private final static String ACTION_CHECK_IN_PROCESSED = ".checkInProcessed";
private final static String ACTION_GET_CHECKINS_PROCESSED = ".getCheckinsProcessed";
private final static String ACTION_FIND_NEARBY_POIS_WITH_CHECKINS_PROCESSED = ".findNearbyPOIsWithCheckinsProcessed";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.msalinger.checkinmanager.CheckinService.getPOIProcessed")) {
tv = (TextView)findViewById(R.id.textBox1);
Bundle incomingData = intent.getExtras();
String st = "";
if (incomingData.getBoolean("result")) {
ArrayList<POI> poiList = incomingData.getParcelableArrayList("poList");
st = printPOI(poiList);
}
else {
st = incomingData.getString("error");
}
}
else if (intent.getAction().equals(INTENT_BASE_URI + ACTION_CHECK_IN_PROCESSED)) {
}
else if (intent.getAction().equals(INTENT_BASE_URI + ACTION_GET_CHECKINS_PROCESSED)) {
}
else if (intent.getAction().equals(INTENT_BASE_URI + ACTION_FIND_NEARBY_POIS_WITH_CHECKINS_PROCESSED)) {
}
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.msalinger.checkinmanagerdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:enabled="true"
android:name="com.msalinger.checkinmanager.CheckinService" />
<receiver
android:name=".CheckinReceiver">
<intent-filter>
<action android:name="com.msalinger.checkinmanager.CheckinService.getPOIProcessed" />
</intent-filter>
<intent-filter>
<action android:name="com.msalinger.checkinmanager.CheckinService.checkInProcessed" />
</intent-filter>
<intent-filter>
<action android:name="com.msalinger.checkinmanager.CheckinService.getCheckinsProcessed" />
</intent-filter>
<intent-filter>
<action android:name="com.msalinger.checkinmanager.CheckinService.findNearbyPOIsWithCheckinsProcessed" />
</intent-filter>
</receiver>
</application>
</manifest>
What am I doing wrong? Note that the IntentService exists as part of an Android class library with a different package than the Main activity.
Because the receiver exists to update data in the activity, it should be registered when the activity resume and unregistered when the activity pause. And it should not be in the manifest (see the doc for this).
If it's not the case, it shouldn't be a subclass of your activity.
In all cases, I think your Receiver is not called because it has not the right name in the manifest. It may be something like this : .MainActivity$CheckinReceiver.