How to integrate hockey App with Hybrid mobile app - ionic-framework

I am trying to integrate my Hybrid Mobile App (Inonic + Cordova) with hockey App
but the problem is Hockey App is support Native apps (According to my info). So is there any guide available for that?
Hybrid App integration with Hockey app.
When I try to follow hockey app integration with android platform (hybrid app) it also said me to add some code in main activity so where i can find this

Main activity is inside Android platform... cordova/platforms/android/src/...
Put in onCreate method the Register...
There also some plugins for help in this task like https://github.com/peutetre/cordova-plugin-hockeyapp
Take into account that a lot of crash JavaScript problems do not crash in native world it would be helpful to use additional way to communicate controlled errors for example the saveException method, try to expose this by plugin into javascript, it will let store context information error: http://hockeyapp.net/help/sdk/android/3.0.1/net/hockeyapp/android/ExceptionHandler.html
I have tested the solution for Android only in a fork of the previous mentioned plugin:
https://github.com/m-alcu/cordova-plugin-hockeyapp
There are several actions available but yo only need to use "start" and "saveException" for controlled errors to be send to hockeyapps.
hockeyapp.js:
var exec = require('cordova/exec');
var hockeyapp = {
start:function(success, failure, token) {
exec(success, failure, "HockeyApp", "start", [ token ]);
},
feedback:function(success, failure) {
exec(success, failure, "HockeyApp", "feedback", []);
},
saveException:function(success, failure, description) {
exec(success, failure, "HockeyApp", "saveException", [ description ]);
}
};
module.exports = hockeyapp;
hockeyapp.java:
package com.zengularity.cordova.hockeyapp;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import android.widget.Toast;
import static net.hockeyapp.android.ExceptionHandler.saveException;
import net.hockeyapp.android.FeedbackManager;
import net.hockeyapp.android.CrashManager;
import net.hockeyapp.android.CrashManagerListener;
public class HockeyApp extends CordovaPlugin {
public static boolean initialized = false;
public static String token;
public static String description;
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
if (action.equals("start")) {
token = args.optString(0);
CrashManager.register(cordova.getActivity(), token, null);
initialized = true;
callbackContext.success();
return true;
} else if(action.equals("feedback")) {
token = args.optString(0);
FeedbackManager.register(cordova.getActivity(), token, null);
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
FeedbackManager.showFeedbackActivity(cordova.getActivity());
}
});
callbackContext.success();
return true;
} else if(action.equals("saveException")) {
description = args.optString(0);
if(initialized) {
Toast toast = Toast.makeText(cordova.getActivity(), "problem", Toast.LENGTH_SHORT);
toast.show();
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Exception e = new Exception("Send problem");
saveException(e, new CrashManagerListener() {
public String getDescription() {
return description;
}
});
}
});
callbackContext.success();
return true;
} else {
callbackContext.error("cordova hockeyapp plugin not initialized, call start() first");
return false;
}
}
else {
return false;
}
}
}
example of use this plugin in a hellowold example (index.js):
var app = {
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
// Update DOM on a Received Event
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
console.log('Received Event: ' + id);
hockeyapp.start(
function() { alert('hockeyapp initialised'); },
function(msg) { alert(msg); },
'< your APP ID >');
hockeyapp.saveException(
function() { alert('hockeyapp saveException'); },
function(msg) { alert(msg); },
'Something wrong has happened: bla bla bla...');
}
};
app.initialize();
Hockey stores these controlled exceptions in the file directory of the app and asks to send it the next time user opens app:

Related

MoPub initialization with SdkInitializationListener

I like to initialize MoPub SDK in Android and continue loading banners and interstitials only if SDK init is complete and successful.
What can be a good way to accomplish this?
create a variable listner :
private SdkInitializationListener Listner2;
then put this code inside your oncreate :
final SdkConfiguration.Builder configBuilder = new SdkConfiguration.Builder("24534e1901884e398f1253216226017e");
configBuilder.withLogLevel(DEBUG);
Listner2 = new SdkInitializationListener() {
#Override
public void onInitializationFinished() {
Log.d("MoPub", "SDK initialized");
mInterstitial.load();
}
};
MoPub.initializeSdk(this, configBuilder.build(), Listner2);
The code above load test interstitial if SDK init is complete and successful.
Very easy to accomplish with Android's new Livedata objects. There objects are observable and you can receive their changes wherever you want in your app.
Technology and patterns used:
Livedata
Singleton pattern
MoPub SDK 5.11.1
I will show you how by code snippets
Singleton pattern
public class MoPubSdk {
private static MoPubSdk INSTANCE;
public static MoPubSdk getInstance(Activity activity) {
if(MoPubSdk.INSTANCE == null) {
MoPubSdk.INSTANCE = new MoPubSdk(activity);
}
return MoPubSdk.INSTANCE;
}
}
Constructor with SdkInitializationListener function
Note the MutableLiveData object that changes it's value to true (isInitialized) when the listener is called and the MoPub SDK is ready to call ads. Also see the showConsentIfNeeded function which you can see in the next code block. Just comment the function if not needed.
public class MoPubSdk {
private final MutableLiveData<Boolean> isMoPubSdkInitialized = new MutableLiveData<>();
private Activity mActivity;
private MoPubSdk(Activity activity) {
this.mActivity = activity;
SdkConfiguration sdkConfiguration = new SdkConfiguration.Builder("ANYadunitID")
.withLogLevel(BuildConfig.DEBUG ? MoPubLog.LogLevel.DEBUG : MoPubLog.LogLevel.NONE)
.build();
MoPub.initializeSdk(activity, sdkConfiguration, initSdkListener());
}
private SdkInitializationListener initSdkListener() {
return new SdkInitializationListener() {
#Override
public void onInitializationFinished() {
/* MoPub SDK initialized.
Check if you should show the consent dialog here, and make your ad requests. */
Log.d("MoPub", "SDK initialized");
isMoPubSdkInitialized.setValue(true);
showConsentIfNeeded();
}
};
}
public LiveData<Boolean> isMoPubSdkInitialized() {
return isMoPubSdkInitialized;
}
}
Optional consent Dialog
private void showConsentIfNeeded() {
PersonalInfoManager mPersonalInfoManager = MoPub.getPersonalInformationManager();
Log.d("customeee", "Can collect pers information? "+MoPub.canCollectPersonalInformation()
+ ".\nShould show consent dialog? "+mPersonalInfoManager.shouldShowConsentDialog());
if(!MoPub.canCollectPersonalInformation()) {
if(mPersonalInfoManager.shouldShowConsentDialog()) {
mPersonalInfoManager.loadConsentDialog(new ConsentDialogListener() {
#Override
public void onConsentDialogLoaded() {
mPersonalInfoManager.showConsentDialog();
}
#Override
public void onConsentDialogLoadFailed(#NonNull MoPubErrorCode moPubErrorCode) {
MoPubLog.i("Consent dialog failed to load.");
}
});
}
}
}
So much for initialization. Now let's call the MoPub SDK from an activity and continue with banner loading.
public class MyActivity extends Activity {
private MoPubSdk moPubSdk;
protected void onCreate(final Bundle savedInstanceState) {
moPubSdk = MoPubSdk.getInstance(this);
moPubSdk.isMoPubSdkInitialized().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(Boolean aBoolean) {
if (aBoolean)
//Init your banner here.
}
});
}
}
The LiveData is easy to explain. First time the MoPub SDK initialization begins the Livedata object is false. It takes some time to init, on success the value switches to true and the observer gets called, you can begin banner loading.
On switching activities during init or call MoPubSdk#getInstance another time, the value is already true and gets passed directly on #observe call and you init your banner straight away.

How to handle two calls and the loading controller in Ionic 4

I have a requirement where I have 2 API calls, and I want the first two calls to be there for the first request. And 2nd API call to be there when navigated back.
I am calling 1st API in ngOnInit webhook and 2nd API on ionViewWillEnter webhook.
The issue which I am facing is sometimes my loader doesn’t get dismissed when both of the request complete at the same time.
So the possible solution which I am thinking is that if I could call both APIs on the first load synchronously and thereafter call another API every time the back button is clicked.
NOTE: I am using loaders in my interceptor.
CODE: For interceptor
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Clone the request to add the new header.
const authReq = req.clone();
this.showLoading();
// send the newly created request
return next.handle(authReq).pipe(catchError((error) => {
if (error.status === 401) {
this._navCtrl.navigateForward('/login');
}
return throwError(error);
}), finalize( () => {
console.log('hi');
this.dismissLoading();
})
);
}
EDIT:
Code to show loader and hide loader:
async showLoading() {
return await this._loadingCtrl.create().then(a => {
a.present();
});
}
async dismissLoading() {
return await this._loadingCtrl.dismiss();
}
In my case, I will create a LoaderService to handle the Loading by myself. The special thing is I will create a flag called isShowing, so if the loading is already showing, we just need to update the loading message by calling presentLoader function again. There will be only one Loading popup show up on your screen.
In your case, I would not recommend to display the Loader in HTTP Interceptor because we cannot handle the HTTP call stack there. Just create a new function that combines all necessary API calls and show/dismiss popup when you start/finish processing the data.
import { LoadingController } from '#ionic/angular';
import { Injectable } from '#angular/core';
#Injectable()
export class LoaderService {
private loading: HTMLIonLoadingElement;
private isShowing = false;
constructor(private loadingController: LoadingController) {}
public async presentLoader(message: string): Promise<void> {
if (!this.isShowing) {
this.loading = await this.loadingController.create({
message: message
});
this.isShowing = true;
return await this.loading.present();
} else {
// If loader is showing, only change text, won't create a new loader.
this.isShowing = true;
this.loading.message = message;
}
}
public async dismissLoader(): Promise<void> {
if (this.loading && this.isShowing) {
this.isShowing = false;
await this.loading.dismiss();
}
}
}
The simple solution would be to make a function call whenever you click the bak button and inside the function you can make a API call.
Instead of linking to the back button you can use ionViewWillEnter, which is called whenever you are about to leave a page but the downside would be it is called every time view is changed regardless of the fact that only when back button is clicked.
Also you should check, is your service singleton and it creates a single instance of ionic-loader. I think in your case more than one instance of loader is being created.
Also instead of calling the loader in interceptor, you can call showLoading() in ionViewWillEnter and hideLoading() in ionViewDidEnter() of your page.
You can create a Singleton Loader Service as shown below.
This service will take care of creating only a single instance of ionic loader.
import { Injectable } from '#angular/core';
import { LoadingController } from '#ionic/angular';
#Injectable({
providedIn: 'root'
})
export class LoaderService {
private loader: HTMLIonLoadingElement;
constructor(private loadingController: LoadingController) {}
async showLoader() {
if (!this.loader) {
this.loader = await this.loadingController.create({ message: 'Loading' });
}
await this.loader.present();
}
async hideLoader() {
if (this.loader) {
await this.loader.dismiss();
this.loader = null;
}
}
}
private loading: HTMLIonLoadingElement;
constructor(public loadingController: LoadingController) { }
public async show(): Promise<void> {
return await this.loadingController.create({
message: 'Please wait...',
spinner: 'crescent'
}).then(a => {
a.present().then(() => {
console.log('presented');
});
});
}
return await this.loadingController.dismiss().then(() =>
console.log('dismissed'));
}`enter code here`

Windows Phone: how to manage shake events?

The accelerometer is activated (if I set ReadingChanged it works).
Why the shaking event isn't handled?
namespace AppExample
{
public sealed partial class MainPage : Page
{
private Accelerometer accel;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
accel = Accelerometer.GetDefault();
//accel.ReadingChanged += accel_ReadingChanged;
accel.Shaken += accel_Shaken;
}
void accel_Shaken(Accelerometer sender, AccelerometerShakenEventArgs args)
{
Debug.WriteLine("shaken");
}
}
}
If you mind, there is helper librairy called ShakeGestures to handle shake gestures for windows phone 8. check this question
If you're running Windows Phone 8 , Shaken event won't trigger and does not raise any errors according to MSDN page.
Otherwise it seems like a weird bug to me , I couldn't find any information about it.
You can call the Dispatcher in order to show the result on the main thread.
namespace AppExample
{
public sealed partial class MainPage : Page
{
Accelerometer accel;
public MainPage()
{
this.InitializeComponent();
accel = Accelerometer.GetDefault();
accel.ReadingChanged += accel_ReadingChanged;
accel.Shaken += accel_Shaken;
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
LabelTest.Text = "Shaken!! " + args.Reading.AccelerationX.ToString();
});
async private void accel_Shaken(object sender, AccelerometerShakenEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_shakeCount++;
ScenarioOutputText.Text = _shakeCount.ToString();
});
}
}
}

Stripe checkout with gwt not working

I'm trying to integrate Strip checkout flow in my gwt application. As per the documentation on
https://stripe.com/docs/checkout#integration-custom
we make the configure call and then add a payment completion event handler. But for some reason, the javascript is unable to find the callback function (token)
Uncaught TypeError: undefined is not a function
checkout.js:2 TokenCallback.trigger
checkout.js:2 __bindcheckout.js:2 (anonymous function)
checkout.js:2 IframeView.closed
checkout.js:2 __bindcheckout.js:1 RPC.processMessage
checkout.js:1 __bindcheckout.js:1 RPC.message
checkout.js:1 (anonymous function)
The hooks for opened/closed are getting called though
public class StripePaymentHandler {
public static void initialize(final String apiKey) {
if (!isInjected()) {
ScriptInjector.fromUrl("https://checkout.stripe.com/checkout.js").setWindow(ScriptInjector.TOP_WINDOW)
.setCallback(new Callback() {
#Override
public void onFailure(Exception e) {
Window.alert("Failed to load stripe");
}
#Override
public void onSuccess(Void aVoid) {
doInitialize(apiKey);
}
}).inject();
}
}
public static native void doInitialize(String apiKey) /*-{
console.log('initializing Stripe: '+apiKey);
$wnd.callback = function(token) {
console.log(token);
alert(token);
}
$wnd.handler = $wnd.StripeCheckout.configure({
key: 'key',
image: '/images/logo.png',
token: $wnd.callback
});
}-*/;
public static void completePayment(StripeCheckoutToken token) {
Window.alert(token.getId());
}
public static native void handlePaymentButtonClicked(String description, double price) /*-{
$wnd.handler.open({
name: 'Ziplly',
description: description,
amount: price,
key: 'key',
token: function(token) {
console.log(token);
alert(token);
},
opened: function() {
alert('opened');
}
});
}-*/;
public static native boolean isInjected() /*-{
return typeof $wnd.Stripe !== "undefined";
}-*/;
}
I was able to verify that $wnd.handler does exist after the configure method call. I also tried putting the callback in handler.open method but no luck. Any help on this will be appreciated.
EDIT 2
Here's button handler code that calls handler.open(). This works just fine but the callback from configure method (token) never gets called instead I get the error I described above. Does that make sense?
#Override
public void onSuccess(CheckBuyerEligibilityForCouponResult result) {
PaymentProviderName providerName = result.getPaymentSetupResponse().getProviderName();
switch (providerName) {
case GOOGLE:
handleGooglePayment(result.getPaymentSetupResponse());
break;
case STRIPE:
StripePaymentHandler.handlePaymentButtonClicked("Coupon purchase", 20);
}
I had to add the ID of the button to the StripeCheckout.configure() method to solve this problem. Here's how it would look for you:
$wnd.handler = $wnd.StripeCheckout.configure(
$wnd.myButton.id,
{
key: 'key',
image: '/images/logo.png',
token: $wnd.callback
});

Facebook: FB.apiClient TypeError: $wnd.FB.Facebook is undefined" why this error occures?

We are facing one problem with facebook.
we integrated FB in our web application, when user login through fconnect in our web application then he registered with our system(1st time only) just providing his email id.For normal user few user i/p for registration in our system
Our web-application developed in java [GWT2.0].
Problem is when FACEBOOK or normaluser login through FB in our web-application.( 1 at a time)
when user refreshes page then FB pop window Occues with message
"Debug: Exception while loading FB.apiClient TypeError: $wnd.FB.Facebook is undefined"
or sometimes $wnd.FB.Facebook.apiClient is null occures
we get above error[pop-up] message 3 times.
we used following script in html page
< script type="text/javascript" language="javascript"
src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php">
In only 1 page of our web-application i.e UserHome page where we display users info .
on that page only above error message occurs
We used following GWT Code [from Gwittit] In controller class[Singleton class ]
/**
* Function get called when all the data on first page get loaded.
*
* */
public void notifyFinishedLoadinPage() {
FacebookConnect.waitUntilStatusReady(new
RenderAppWhenReadyCallback());
}
private MyLoginCallback
loginCallback = new MyLoginCallback();
class MyLoginCallback implements LoginCallback {
public void onLogin() {
isFacebookSign = true;
fbLoggedInUserId = ApiFactory.getInstance().getLoggedInUser();
for (FacebookObserver Observer : facebookObservers) {
Observer.notifyFacebookLogin(true);
}
}
}
public void publishStream(final FacebookObserver fbObserver) {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
FacebookConnect.requireSession(new
AsyncCallback() {
public void onFailure(Throwable caught) {
Window.alert("Require session failed: " + caught);
GWT.log("Require session failed: " + caught, null);
}
public void onSuccess(Boolean isLoggedIn) {
if (isLoggedIn) {
for (FacebookObserver Observer :
facebookObservers) {
Observer.notifyPublishStream();
}
}
}
});
}
public void facebookConnection() {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
//SERVER
FacebookConnect.requireSession(new
AsyncCallback() {
public void onFailure(Throwable caught) {
GWT.log("Require session failed: " + caught, null);
}
public void onSuccess(Boolean isLoggedIn) {
if (loginCallback != null && isLoggedIn) {
loginCallback.onLogin();
} else {
//User not logged in
}
}
});
}
/**
* Fired when we know users status
*/
private class RenderAppWhenReadyCallback implements
AsyncCallback {
public RenderAppWhenReadyCallback() {
FacebookConnect.init(FacebookConstants.FACEBOOK_API_KEY,
"xd_receiver.htm", loginCallback);
//SERVER
}
public void onFailure(Throwable caught) {
Window.alert("Unable to login through Facebook: " + caught);
}
public void onSuccess(ConnectState result) {
if (result == ConnectState.connected) {
isFacebookSign = true;
for (FacebookObserver Observer : facebookObservers) {
Observer.notifyFacebookLogin(true);
}
//History.newItem(HistoryConstants.USERHOME_PAGE_HISTORY_TOKEN);
} else {
//rightSideFlexTable.clearCell(0, 0);
//rightSideFlexTable.setWidget(0, 0,
facebookPanel);
isFacebookSign = false;
}
}
};
Now we unable to found solution to this problem.
Can any one help Us to solve this problem ASAP
Hope-for the Best Co-operation
we found solution for above Question.
Facebook (login)loading requires few time.
In Our web page we fetch fb details like fb users loggedInId ,Image,etc.
so at the time of page loading we get all values null because facebook not load properly
so we get $wnd.FB.Facebook.apiClient is null or
Debug: Exception while loading FB.apiClient TypeError: $wnd.FB.Facebook is undefined"
To solve this problem we write one method which calls when user refreshes page or after facebook loading done properly.
public void notifyFacebookLogin(boolean isLogin) {
Long fbLoggedInUserId = ApiFactory.getInstance().getLoggedInUser();
if (fbLoggedInUserId != null) {
if (globalEndUserInfo == null) {
globalEndUserInfo = new EndUserInfo();
globalEndUserInfo.setFbLoggedInUserId(fbLoggedInUserId);
}
}
// code wherever we deal with FB related object
}
Now no error message display when user refreshes page or if fb takes time to loading
In this way we solve our Problem. :)