I am unable to pass data from java activity to react native.
I am processing a card payment, and when the payment is done, the response is stored in a variable called message. I need to pass this message to my react native code.
// Java module, the data I want to pass is in "message"
public class HelloWorldModule extends ReactContextBaseJavaModule implements ActivityEventListener{
Activity activity;
ReactApplicationContext reactContext;
public HelloWorldModule(ReactApplicationContext reactContext,Activity activity) {
super(reactContext); //required by React Native
this.reactContext= reactContext;
this.activity= activity;
reactContext.addActivityEventListener(this); //Register this native module as Activity result listener
}
#Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
// ReactApplicationContext reactContext = this.getReactNativeHost().getReactInstanceManager().getCurrentReactApplicationContext();
// reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit();
// reactContext
// .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
// .emit('message', message);
/*
* We advise you to do a further verification of transaction's details on your server to be
* sure everything checks out before providing service or goods.
*/
if (requestCode == RaveConstants.RAVE_REQUEST_CODE && data != null) {
String message = data.getStringExtra("response");
// Log.e("RAVE",message);
if (resultCode == RavePayActivity.RESULT_SUCCESS) {
Toast.makeText(activity, "SUCCESS " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_ERROR) {
Toast.makeText(activity, "ERROR " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_CANCELLED) {
Toast.makeText(activity, "CANCELLED " + message, Toast.LENGTH_SHORT).show();
}
}
// else {
// super.onActivityResult(activity, requestCode, resultCode, data);
// }
}
// #Override
// public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
// Toast.makeText( activity , "hello", Toast.LENGTH_SHORT).show();
// }
#Override
public void onNewIntent(Intent intent) {
}
#Override
//getName is required to define the name of the module represented in JavaScript
public String getName() {
return "HelloWorld";
}
#ReactMethod
public void sayHi(Callback errorCallback, Callback successCallback) {
try{
int amount = 30;//call.argument("amount");
String narration = "Payment for soup";//call.argument("nara");
String countryCode = "NG"; //call.argument("countryCode");
String currency = "NGN"; //call.argument("currency");
String amountText = "50";//call.argument("amountText");
String email = "*****#yahoo.com";//call.argument("email");
String name = "Ubanna Danny";//call.argument("name");
String paymentId = "a98sjkhdjdu";//call.argument("paymentId");
String key ="FLWPUBK-****-X";
String encryptionKey = "****";
new RavePayManager(activity).setAmount(Double.parseDouble(String.valueOf(amount)))
.setCountry(countryCode)
.setCurrency(currency)
.setEmail(email)
.setfName(name)
.setlName("")
.setNarration(narration)
.setPublicKey(key)
.setEncryptionKey(encryptionKey)
.setTxRef(paymentId)
.acceptMpesaPayments(false)
.acceptAccountPayments(true)
.acceptCardPayments(true)
.acceptGHMobileMoneyPayments(false)
.onStagingEnv(false)
.allowSaveCardFeature(true)
.initialize();
} catch (IllegalViewOperationException e) {
errorCallback.invoke(e.getMessage());
}
}
}
// React native code
// async function to call the Java native method
async sayHiFromJava() {
HelloWorld.sayHi( (err) => {console.log(err)}, (msg) => {console.log(msg)} );
}
Please help.
use device emitter to send data from native to react native
in on activity result add following code
ReactContext context = this.getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit();
context
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit('message', message);
in react native add Dives emiter listener
import {DeviceEventEmitter} from 'react-native';
EmitterModule.addListener('message', (message) => {
console.log(message);
};
Related
Geofences are not being triggered using Broadcast Receiver. It was working with IntentService, however it wasn't working when the application is background.. I have changed to Broadcast receiver to make it work irrespective if the application is running in Foreground or background. After I changed it to Broadcast receiver by looking the below example, it stopped working even for Entry and Dwell...
https://github.com/googlesamples/android-play-location/tree/master/Geofencing/app/src/main/java/com/google/android/gms/location/sample/geofencing
Main Activity
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {
private static final String TAG = "Geofence example";
private static final int MULTIPLE_PERMISSIONS = 1;
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private static final String ADDRESS_REQUESTED_KEY = "address-request-pending";
private static final String LOCATION_ADDRESS_KEY = "location-address";
String[] permissions = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_SMS,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS};
private GeofencingClient mGeofencingClient;
private PendingIntent mGeofencePendingIntent;
private Context mContext;
/**
* Provides access to the Fused Location Provider API.
*/
private FusedLocationProviderClient mFusedLocationClient;
/**
* Represents a geographical location.
*/
private Location mLastLocation;
/**
* Tracks whether the user has requested an address. Becomes true when the user requests an
* address and false when the address (or an error message) is delivered.
*/
private boolean mAddressRequested;
/**
* The formatted location address.
*/
private String mAddressOutput;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* Displays the location address.
*/
private TextView mLocationAddressTextView;
/**
* Visible while the address is being fetched.
*/
private ProgressBar mProgressBar;
/**
* Kicks off the request to fetch an address when pressed.
*/
private Button mFetchAddressButton;
private List<Geofence> mGeofenceList;
private GoogleApiClient mGoogleApiClient;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResultReceiver = new AddressResultReceiver(new Handler());
mLocationAddressTextView = (TextView) findViewById(R.id.location_address_view);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
mFetchAddressButton = (Button) findViewById(R.id.fetch_address_button);
// Set defaults, then update using values stored in the Bundle.
mAddressRequested = false;
mAddressOutput = "";
mContext = this;
updateValuesFromBundle(savedInstanceState);
mGeofencingClient = LocationServices.getGeofencingClient(this);
//LatLng latLng = getLocationFromAddress(mContext, "517 Carrville Rd, Richmond Hill, ON L4C 6E5");
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
SmsReceiver.bindListener(new SMSListener() {
#Override
public void messageReceived(String messageText) {
//From the received text string you may do string operations to get the required OTP
//It depends on your SMS format
Log.d("Message", messageText);
Toast.makeText(MainActivity.this, "Message: " + messageText, Toast.LENGTH_LONG).show();
//startIntentService();
}
});
Log.d(GeofenceTransitionsIntentService.TAG, "OnCreate - Building google API client");
buildGoogleApiClient();
Log.d(GeofenceTransitionsIntentService.TAG, "OnCreate - Before permission check");
if (checkPermissions()) {
Log.d(GeofenceTransitionsIntentService.TAG, "OnCreate - inside Permission ");
getAddress();
}
Log.d(GeofenceTransitionsIntentService.TAG, "mGoogleApiClient = " + mGoogleApiClient);
//test_sendNotification("testing");
updateUIWidgets();
}
#Override
public void onStart() {
super.onStart();
Log.d(GeofenceTransitionsIntentService.TAG, "onStart - before Permission ");
if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
Log.d(GeofenceTransitionsIntentService.TAG, "getGeofencePendingIntent " + mGeofencePendingIntent);
return mGeofencePendingIntent;
}
/**
* Updates fields based on data stored in the bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Check savedInstanceState to see if the address was previously requested.
if (savedInstanceState.keySet().contains(ADDRESS_REQUESTED_KEY)) {
mAddressRequested = savedInstanceState.getBoolean(ADDRESS_REQUESTED_KEY);
}
// Check savedInstanceState to see if the location address string was previously found
// and stored in the Bundle. If it was found, display the address string in the UI.
if (savedInstanceState.keySet().contains(LOCATION_ADDRESS_KEY)) {
mAddressOutput = savedInstanceState.getString(LOCATION_ADDRESS_KEY);
displayAddressOutput();
}
}
}
/**
* Runs when user clicks the Fetch Address button.
*/
#SuppressWarnings("unused")
public void fetchAddressButtonHandler(View view) {
if (mLastLocation != null) {
Log.d(GeofenceTransitionsIntentService.TAG, "fetchAddressButtonHandler - mLastLocation " + mLastLocation);
startIntentService();
return;
}
// If we have not yet retrieved the user location, we process the user's request by setting
// mAddressRequested to true. As far as the user is concerned, pressing the Fetch Address button
// immediately kicks off the process of getting the address.
mAddressRequested = true;
updateUIWidgets();
}
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
private void startIntentService() {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(Constants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
Log.d(GeofenceTransitionsIntentService.TAG, "startIntentService - addGeoFenceList " + (mGeofenceList != null));
addGeoFence();
}
/**
* Gets the address for the last known location.
*/
#SuppressWarnings("MissingPermission")
private void getAddress() {
Log.d(GeofenceTransitionsIntentService.TAG, "MainActivity - getAddress () ");
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location == null) {
Log.w(GeofenceTransitionsIntentService.TAG, "onSuccess:null");
return;
}
mLastLocation = location;
// Determine whether a Geocoder is available.
if (!Geocoder.isPresent()) {
showSnackbar(getString(R.string.no_geocoder_available));
return;
}
// If the user pressed the fetch address button before we had the location,
// this will be set to true indicating that we should kick off the intent
// service after fetching the location.
if (mAddressRequested) {
startIntentService();
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "getLastLocation:onFailure", e);
}
});
}
private GeofencingRequest getGeofencingRequest() {
Log.d(GeofenceTransitionsIntentService.TAG, "MainActivity - getGeofencingRequest ");
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_DWELL | GeofencingRequest.INITIAL_TRIGGER_EXIT);
builder.addGeofences(mGeofenceList);
return builder.build();
}
private void addGeoFence() {
Log.d(GeofenceTransitionsIntentService.TAG, "MainActivity - mGeofenceList () ");
mGeofenceList = new ArrayList<Geofence>();
for (Map.Entry<String, LatLng> entry : Constants.GEO_FENCE_LIST.entrySet()) {
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
// Set the circular region of this geofence.
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setLoiteringDelay(6000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT | Geofence.GEOFENCE_TRANSITION_DWELL)
// Create the geofence.
.build());
}
Log.d(GeofenceTransitionsIntentService.TAG, "addGeoFenceList - mGeofenceList " + mGeofenceList);
//getGeofencingRequest();
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
Toast.makeText(this, "not connected", Toast.LENGTH_SHORT).show();
return;
}
Log.d(GeofenceTransitionsIntentService.TAG, "addGeoFenceList - mGoogleApiClient " + mGoogleApiClient.isConnected());
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
// The GeofenceRequest object.
getGeofencingRequest(),
// A pending intent that that is reused when calling removeGeofences(). This
// pending intent is used to generate an intent when a matched geofence
// transition is observed.
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.d(GeofenceTransitionsIntentService.TAG, "addGeoFenceList - error " + securityException.getLocalizedMessage());
}
}
/**
* Updates the address in the UI.
*/
private void displayAddressOutput() {
mLocationAddressTextView.setText(mAddressOutput);
}
/**
* Toggles the visibility of the progress bar. Enables or disables the Fetch Address button.
*/
private void updateUIWidgets() {
if (mAddressRequested) {
mProgressBar.setVisibility(ProgressBar.VISIBLE);
mFetchAddressButton.setEnabled(false);
} else {
mProgressBar.setVisibility(ProgressBar.GONE);
mFetchAddressButton.setEnabled(true);
}
}
/**
* Shows a toast with the given text.
*/
private void showToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save whether the address has been requested.
savedInstanceState.putBoolean(ADDRESS_REQUESTED_KEY, mAddressRequested);
// Save the address string.
savedInstanceState.putString(LOCATION_ADDRESS_KEY, mAddressOutput);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Toast.makeText(
this,
"Geofences Added",
Toast.LENGTH_SHORT
).show();
} else {
// Get the status code for the error and log it using a user-friendly message.
Toast.makeText(
this,
"Geofences error - onResult",
Toast.LENGTH_SHORT
).show();
}
}
/**
* Shows a {#link Snackbar} using {#code text}.
*
* #param text The Snackbar text.
*/
private void showSnackbar(final String text) {
View container = findViewById(android.R.id.content);
if (container != null) {
Snackbar.make(container, text, Snackbar.LENGTH_LONG).show();
}
}
private void showSnackbar(final int mainTextStringId, final int actionStringId,
View.OnClickListener listener) {
Snackbar.make(findViewById(android.R.id.content),
getString(mainTextStringId),
Snackbar.LENGTH_INDEFINITE)
.setAction(getString(actionStringId), listener).show();
}
/**
* Return the current state of the permissions needed.
*/
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(getApplicationContext(), p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permissions granted.
getAddress();
} else {
String perStr = "";
for (String per : permissions) {
perStr += "\n" + per;
}
// permissions list of don't granted permission
}
return;
}
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
Log.d(GeofenceTransitionsIntentService.TAG, "buildGoogleApiClient - mGoogleApiClient " + mGoogleApiClient);
}
private class AddressResultReceiver extends ResultReceiver {
AddressResultReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
displayAddressOutput();
// Show a toast message if an address was found.
if (resultCode == Constants.SUCCESS_RESULT) {
showToast(getString(R.string.address_found));
}
Log.d(GeofenceTransitionsIntentService.TAG, "onReceiveResult - onReceiveResult ");
// Reset. Enable the Fetch Address button and stop showing the progress bar.
mAddressRequested = false;
updateUIWidgets();
}
}
}
JobIntentService:
public class GeofenceTransitionsIntentService extends JobIntentService {
protected static final String TAG = "geofence-transitions";
private static final int JOB_ID = 573;
#Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "GeofenceTransitionsIntentService onCreate ");
}
#Override
protected void onHandleWork(#NonNull Intent intent) {
Log.e(TAG, "GeofenceTransitionsIntentService intent " + intent);
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = "error";
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
String geofenceTransitionString = getTransitionString(geofenceTransition);
Log.e(TAG, "geofence_transition_geofenceTransition " + geofenceTransition);
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
this,
geofenceTransition,
triggeringGeofences
);
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails, geofenceTransitionString);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, "geofence_transition_invalid_type" + geofenceTransition);
}
}
/**
* Convenience method for enqueuing work in to this service.
*/
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, GeofenceTransitionsIntentService.class, JOB_ID, intent);
}
private String getGeofenceTransitionDetails(
Context context,
int geofenceTransition,
List<Geofence> triggeringGeofences) {
String geofenceTransitionString = getTransitionString(geofenceTransition);
// Get the Ids of each geofence that was triggered.
ArrayList triggeringGeofencesIdsList = new ArrayList();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return "Entered";
case Geofence.GEOFENCE_TRANSITION_EXIT:
return "Exited";
case Geofence.GEOFENCE_TRANSITION_DWELL:
return "Dwell";
default:
return "unkwn";
}
}
private void sendNotification(String notificationDetails, String geofenceTransitionString) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(getApplicationContext(), "notify_geofence");
Intent ii = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, ii, 0);
//Assign BigText style notification
NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
bigText.bigText(notificationDetails);
bigText.setSummaryText(geofenceTransitionString);
mBuilder.setContentIntent(pendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
mBuilder.setContentTitle("Geofence notification");
mBuilder.setContentText(notificationDetails);
mBuilder.setPriority(Notification.PRIORITY_MAX);
mBuilder.setStyle(bigText);
NotificationManager mNotificationManager =
(NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("notify_001",
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
}
mNotificationManager.notify(new Random().nextInt(61) + 20, mBuilder.build());
}
}
Broadcast receiver:
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Enqueues a JobIntentService passing the context and intent as parameters
GeofenceTransitionsIntentService.enqueueWork(context, intent);
}
}
Logs:
2018-10-30 12:40:02.850 24811-24811/com.lakshmiapps.findme D/geofence-transitions: fetchAddressButtonHandler - mLastLocation Location[fused 43.849304,-79.449305 hAcc=14 et=+2d21h3m43s23ms alt=161.3000030517578 vAcc=2 sAcc=??? bAcc=??? {Bundle[mParcelledData.dataSize=52]}]
2018-10-30 12:40:02.857 24811-24811/com.lakshmiapps.findme D/geofence-transitions: startIntentService - addGeoFenceList false
2018-10-30 12:40:02.857 24811-24811/com.lakshmiapps.findme D/geofence-transitions: MainActivity - mGeofenceList ()
2018-10-30 12:40:07.819 24811-24811/com.lakshmiapps.findme D/geofence-transitions: addGeoFenceList - mGeofenceList [Geofence[CIRCLE id:Ross Doan transitions:7 43.857670, -79.443370 1000m, resp=0s, dwell=6000ms, #-1], Geofence[CIRCLE id:Niagara falls transitions:7 43.078350, -79.081910 1000m, resp=0s, dwell=6000ms, #-1], Geofence[CIRCLE id:Taste of Malayalees transitions:7 43.635190, -79.622830 1000m, resp=0s, dwell=6000ms, #-1], Geofence[CIRCLE id:Home transitions:7 43.849301, -79.449306 1000m, resp=0s, dwell=6000ms, #-1], Geofence[CIRCLE id:Luv2Play transitions:7 43.855660, -79.430200 1000m, resp=0s, dwell=6000ms, #-1]]
2018-10-30 12:40:09.534 24811-24811/com.lakshmiapps.findme D/geofence-transitions: addGeoFenceList - mGoogleApiClient true
2018-10-30 12:40:09.534 24811-24811/com.lakshmiapps.findme D/geofence-transitions: MainActivity - getGeofencingRequest
2018-10-30 12:40:13.598 24811-24811/com.lakshmiapps.findme D/geofence-transitions: getGeofencePendingIntent PendingIntent{5fddab6: android.os.BinderProxy#47dc3b7}
2018-10-30 12:40:13.631 4938-5579/? I/GeofencerStateMachine: addGeofences called by com.lakshmiapps.findme
2018-10-30 12:40:13.631 4726-4773/? E/GmsLocationManagerService_FLP: [GeofencingApi] AddGeofence from com.lakshmiapps.findme and size = 5
2018-10-30 12:40:13.632 4726-4773/? D/GeofenceRequestInfo_FLP: removeExpiredGeofences - com.lakshmiapps.findme: 0 fences
2018-10-30 12:40:13.632 4726-4773/? E/GeofenceRequestManager_FLP: [GeofencingApi] AddGeofence 5 fences from com.lakshmiapps.findme
2018-10-30 12:40:13.632 4726-4773/? D/GeofenceRequestManager_FLP: 1540668973552 gpslastknowntime: 243443714 / nlplastknowntime: 248290794
2018-10-30 12:40:16.290 24811-24811/com.lakshmiapps.findme D/geofence-transitions: onReceiveResult - onReceiveResult
2018-10-30 12:44:08.692 4938-24505/? I/GeofencerStateMachine: removeGeofences: removeRequest=RemoveGeofencingRequest[REMOVE_BY_PENDING_INTENT pendingIntent=PendingIntent[creatorPackage=com.marriott.mrt], packageName=null]
Thanks,
Ramesh
Adding
<uses-permission android:name="android.permission.WAKE_LOCK" />
to AndroidManifest.xml seems to solve this issue in my case
I am trying to develop and app that listens and speaks back to the user. I am trying to make it as handsfree as possible.
My issue is that if the user does not respond in time, the SpeechRecognition will timeout, and the user will need to press the button to start listening again.
*Is there a way for me to do a work around where if nothing is heard by the application, it can prompt to try again and restart the listener?
CODE:
//Function i call when a user input is required.
private void promptSpeechInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
try {
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
} catch (ActivityNotFoundException a) {
Toast.makeText(getApplicationContext(),
getString(R.string.speech_not_supported),
Toast.LENGTH_SHORT).show();
}
}
/**
* Receiving speech input
* */
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
System.out.println("REQUEST CODE: " + requestCode);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
System.out.println("resultCode: " + resultCode);
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
txtSpeechInput.setText(result.get(0));
input = result.get(0).toLowerCase();
}
break;
}
}
}
I also have code that will read text to the user, and then prompt for voice input after its finished.
Please let me know if i can provide more details or code. Thanks much!
To make google speech handsfree without clicking the "mic button", you have to make your own class for the recognizer, i wrote the code in xamarin-android, so it's pretty similar on java :
Public class CustomRecognizer : Java.Lang.Object, IRecognitionListener, TextToSpeech.IOnInitListener
{
private SpeechRecognizer _speech;
private Intent _speechIntent;
public string Words;
public CustomRecognizer(Context _context)
{
this._context = _context;
Words = "";
_speech = SpeechRecognizer.CreateSpeechRecognizer(this._context);
_speech.SetRecognitionListener(this);
_speechIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
_speechIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
_speechIntent.PutExtra(RecognizerIntent.ActionRecognizeSpeech, RecognizerIntent.ExtraPreferOffline);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1000);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1000);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 1500);
}
void startover()
{
_speech.Destroy();
_speech = SpeechRecognizer.CreateSpeechRecognizer(this._context);
_speech.SetRecognitionListener(this);
_speechIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1000);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1000);
_speechIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 1500);
StartListening();
}
public void StartListening()
{
_speech.StartListening(_speechIntent);
}
public void StopListening()
{
_speech.StopListening();
}
public void OnBeginningOfSpeech()
{
}
public void OnBufferReceived(byte[] buffer)
{
}
public void OnEndOfSpeech()
{
}
public void OnError([GeneratedEnum] SpeechRecognizerError error)
{
Words = error.ToString();
startover();
}
When the recognizer got timeout, it will call OnError Event
. On my code, i put startover() to restart the recording.
trying to use in app billing in Android at the moment.
Everything works fine and I can purchase items and query existing ones but my OnIabPurchaseFinishedListener listener is not being called during a successful purchase. It is called when there is an issue but not on a completed purchase.
I have my main activity, with fragments and a navigation drawer. (fragments are not touched here. I have a helper class that all the billing happens in.
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, MyBilling.Update {\
MyBilling bill;
OnCreate(){
bill = new MyBilling(this, this);
bill.onCreate();
}
private void RemoveAdsClick()
{
bill.purchaseRemoveAds();
}
public void NewPurchaseUpdate(){
tinydb.putBoolean("Premium", true);
nav_Menu.findItem(R.id.remove_ad_button).setVisible(false);
displaySelectedScreen(R.id.distance_check); // Reload screen
}
}
public class MyBilling extends Activity {
////Interface
public interface Update {
void NewPurchaseUpdate();
}
// Debug tag, for logging
static final String TAG = "XXXXXX";
static final String SKU_REMOVE_ADS = "remove_ads";
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10111;
// Activity
Activity activity;
// The helper object
IabHelper mHelper;
String base64EncodedPublicKey = "xxxxxxxx";
String payload = "xxxxx";
public boolean isAdsDisabled = false;
public boolean AdCheck = false;
////Instance of interface
Update myActivity;
public MyBilling(Activity launcher,Update activity) {
this.activity = launcher;
myActivity = activity;
}
// User clicked the "Remove Ads" button.
public void purchaseRemoveAds() {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mHelper.launchPurchaseFlow(activity, SKU_REMOVE_ADS,
RC_REQUEST, mPurchaseFinishedListener, payload);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (mHelper == null) return;
// Pass on the activity result to the helper for handling
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
// not handled, so handle it ourselves (here's where you'd
// perform any handling of activity results not related to in-app
// billing...
super.onActivityResult(requestCode, resultCode, data);
}
else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener()
{
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: "
+ purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null)
return;
if (result.isFailure()) {
complain("Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_REMOVE_ADS)) {
// bought the premium upgrade!
myActivity.NewPurchaseUpdate();
Log.d(TAG, "New Purchase Update Method was called");
}
}
};
}
some googling showed that it could be an issue with onActivityResult not being in the helper class. So I made billing class extend activity and then added onActivityResult and #Override but this also is not called with any breakpoints.
As mentioned above, OnIabPurchaseFinishedListener is called for a failed purchase (already own item) but not for a successful one.
Any help here would be great, I have tried to keep the code as light as possible to help with reading. If I'm missing anything please let me know.
I have fixed this issue by ditching my helper class for now and moving the billing tasks into the main activity.
I have implemented In-App Billing in my Activity following the google GitHub example
this is my code:
public class Premium extends Activity implements IabBroadcastReceiver.IabBroadcastListener {
Button premium;
//toast
Context context = getBaseContext();
int duration = Toast.LENGTH_SHORT;
//debug tag
static final String TAG = "CHORDS";
//does the user have premium?
boolean mIsPremium = false;
//SKUs
static final String SKU_PREMIUM = "chords_premium";
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10001;
// The helper object
IabHelper mHelper;
// Provides purchase notification while this app is running
IabBroadcastReceiver mBroadcastReceiver;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.premium_layout);
premium = (Button) findViewById(R.id.premium);
String base64EncodedPublicKey = "Key"
// Create the helper, passing it our context and the public key to verify signatures with
Log.d(TAG, "Creating IAB helper.");
mHelper = new IabHelper(this, base64EncodedPublicKey);
// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up in-app billing: " + result);
return;
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
mBroadcastReceiver = new IabBroadcastReceiver(Premium.this);
IntentFilter broadcastFilter = new IntentFilter(IabBroadcastReceiver.ACTION);
registerReceiver(mBroadcastReceiver, broadcastFilter);
Log.d(TAG, "Setup successful. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabHelper.IabAsyncInProgressException e) {
Log.d(TAG, "Error querying inventory. Another async operation in progress.");
}
}
});
}
// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
Log.d(TAG, "Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
// Do we have the premium upgrade?
Purchase premiumPurchase = inventory.getPurchase(SKU_PREMIUM);
mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
premium.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mIsPremium = true)
premium.setEnabled(false);
else {
}
}
});
};
};
#Override
public void receivedBroadcast() {
// Received a broadcast notification that the inventory of items has changed
Log.d(TAG, "Received broadcast notification. Querying inventory.");
try {
mHelper.queryInventoryAsync(mGotInventoryListener);
} catch (IabHelper.IabAsyncInProgressException e) {
Log.d(TAG, "Error querying inventory. Another async operation in progress.");
}
}
// User clicked the "Upgrade to Premium" button.
public void onUpgradeAppButtonClicked(View arg0) {
Log.d(TAG, "Upgrade button clicked; launching purchase flow for upgrade.");
/* verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use
* an empty string, but on a production app you should carefully generate this. */
String payload = "";
try {
mHelper.launchPurchaseFlow(this, SKU_PREMIUM, RC_REQUEST,
mPurchaseFinishedListener, payload);
} catch (IabHelper.IabAsyncInProgressException e) {
Log.d(TAG,"Error launching purchase flow. Another async operation in progress.");
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (mHelper == null) return;
// Pass on the activity result to the helper for handling
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
return true;
}
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayload(purchase)) {
Log.d(TAG, "Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_PREMIUM)) {
// bought the premium upgrade!
Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
Toast toast = Toast.makeText(context, R.string.premium_bought, duration);
toast.show();
mIsPremium = true;
updateUI();
}
}
};
// We're being destroyed. It's important to dispose of the helper here!
#Override
public void onDestroy() {
super.onDestroy();
// very important:
if (mBroadcastReceiver != null) {
unregisterReceiver(mBroadcastReceiver);
}
// very important:
Log.d(TAG, "Destroying helper.");
if (mHelper != null) {
mHelper.disposeWhenFinished();
mHelper = null;
}
}
public void updateUI() {
//TODO: elimina pubblicita
}
}
As I wrote above in te title, I need to start the google purchase
when my premium button is pressed. The android documentation is not very clear on how to do this stuff in particular.
What should I put in my OnClick() method to start the purchase flow?
You should call
mHelper.startSetup
on the button click to start the purchase flow.
The data i receive with my smartphone through Bluetooth LE occurs in this method in my service class
public void onCharacteristicRead(BluetoothGattCharacteristic charac, int status)
{
UUID charUuid = charac.getUuid();
Bundle mBundle = new Bundle();
Message msg = Message.obtain(mActivityHandler, HRP_VALUE_MSG);
Log.i(TAG, "onCharacteristicRead");
if (charUuid.equals(BODY_SENSOR_LOCATION))
mBundle.putByteArray(BSL_VALUE, charac.getValue());
msg.setData(mBundle);
msg.sendToTarget();
}
The Handler in the activity class is contructed like this:
private Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case HRPService.HRP_VALUE_MSG:
Log.d(TAG, "mHandler.HRP_VALUE_MSG");
Bundle data1 = msg.getData();
final byte[] bslval = data1.getByteArray(HRPService.BSL_VALUE);
runOnUiThread(new Runnable()
{
public void run()
{
if (bslval != null)
{
try
{
Log.i(TAG, "BYTE BSL VAL =" + bslval[0]);
TextView bsltv = (TextView) findViewById(R.id.BodySensorLocation);
bsltv.setText("\t" + mContext.getString(R.string.BodySensorLocation)
+ getBodySensorLocation(bslval[0]));
}
catch (Exception e)
{
Log.e(TAG, e.toString());
}
}
}
});
default:
super.handleMessage(msg);
}
}
};
Can someone tell med the relationship between those two methods ?. I receive an array of data from the remote device, and i want the data to be shown on the Textview "bsltv". How do i do this ?.
Thanks in advance
I created a class called BLEGattCallback which receives the updates. In this class I implemented the interface which you are mentioned. To receive and display the data I just
send and Intent with the needed informations put into a Bundle. Just create a BroadcastReceiver in your Activity and register it for the Action. Read all data from the Bundle and display it by calling TextView.setText(String).
The UUIDManager is just a class I created to translate the Characteristic into a readable String.
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if(status == BluetoothGatt.GATT_SUCCESS) {
Log.d(CLASSNAME, "onCharacteristicRead for Characteristic: " + characteristic.getUuid().toString());
Log.d(CLASSNAME, "onCharacteristicRead for: " + UUIDManager.getCharacteristic(characteristic.getUuid().toString()));
Intent intent = new Intent();
intent.setAction(ACTION_READ_DATA_AVAILABLE);
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data) {
stringBuilder.append(String.format("%02X ", byteChar));
}
Bundle extras = new Bundle();
extras.putString(EXTRA_CHARACTERISTIC_UUID, characteristic.getUuid().toString());
extras.putString(EXTRA_STRING_DATA, stringBuilder.toString());
extras.putByteArray(EXTRA_RAW_DATA, characteristic.getValue());
extras.putString(EXTRA_DEVICE_ADDRESS, gatt.getDevice().getAddress());
intent.putExtras(extras);
}
m_Context.sendBroadcast(intent);
} else {
Log.e(CLASSNAME, "onCharacteristicRead was not successfull!");
}
}