The pushPlugin.register function is getting called for Android, but not iOS. Here is the code I have.
this.initialize is getting called and I see the first alert there -- alert('PushNotifications:initialize');
Any ideas? why pushPlugin.register and window.onNotificationAPN function don't seem to get called?. At one brief point it was working, IIRC. I'm not sure what changed.
Here's my config setup:
https://gist.github.com/adaptivedev/d33f38cd3d6cf10be9dc
Thanks!
.service('PushNotifications', function(Utility, $cordovaToast, $rootScope) {
alert('PushNotifications');
var pushPlugin = null;
/*
this.deviceRegId = function() {
$rootScope.getFDeviceId();
}
*/
this.initialize = function() {
alert('PushNotifications:initialize');
document.addEventListener('deviceready', function() {
//alert('PushNotifications:initialize:deviceready:device='+JSON.stringify(device));
pushPlugin = window.plugins.pushNotification;
if ( device.platform == 'android' || device.platform == 'Android' || device.platform == "amazon-fireos" ){
pushPlugin.register(
function(result) {
console.log('PushNotifications:initialize:1:result='+result);
},
function(result) {
alert('PushNotifications:initialize:2:result='+result);
console.log(JSON.stringify(result));
},
{
"senderID":"123",
"ecb":"onNotificationGCM"
});
} else {
pushPlugin.register(
function(result) {
alert('PushNotifications:initialize:1:result='+result);
//$rootScope.setDeviceId(result)
},
function(result) {
alert('PushNotifications:initialize:2:result='+result);
console.log(JSON.stringify(result));
},
{
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"onNotificationAPN"
});
}
});
// notifications for Android
window.onNotificationGCM = function(e) {
alert('onNotificationGCM:e='+JSON.stringify(e));
window.boosterNotification = e;
switch( e.event )
{
case 'registered':
if ( e.regid.length > 0 )
{
$rootScope.setDeviceId(e.regid);
}
break;
case 'message':
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if ( e.foreground )
{
// on Android soundname is outside the payload.
// On Amazon FireOS all custom attributes are contained within payload
var soundfile = e.soundname || e.payload.sound;
// if the notification contains a soundname, play it.
//var my_media = new Media("/android_asset/www/"+ soundfile);
//my_media.play();
}
else
{ // otherwise we were launched because the user touched a notification in the notification tray.
if ( e.coldstart )
{
//
}
else
{
//
}
}
var msg = e.payload.message.replace(/<b>/g, "")
msg = msg.replace(/<\/b>/g, "");
$cordovaToast.showShortCenter(msg).then(function(success) {
//$state.go('app.upcoming');
$rootScope.updateNotifications();
}, function (error) {
// error
}
);
//alert(e.payload.message);
//Only works for GCM
// e.payload.msgcnt + '</li>');
//Only works on Amazon Fire OS
// e.payload.timeStamp
break;
case 'error':
//e.msg
break;
default:
// Unknown
break;
}
};
// notifications for iOS
window.onNotificationAPN = function(result) {
alert('onNotificationAPN:result:1:='+JSON.stringify(result));
if ( event.alert )
{
//navigator.notification.alert(event.alert);
}
if ( event.sound )
{
//var snd = new Media(event.sound);
//snd.play();
}
if ( event.badge )
{
//.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
}
console.log('onNotificationAPN:result='+JSON.stringify(result));
window.boosterNotification = result;
};
};
});
I solved it! In Xcode, select the file (PushPlugin.m) and on right side check "Target Membership"
Related
I am trying to implement Google Oauth2 consent screen within a popup but it says redirect URI mismatch. Is there any way where I can set up a web Ouath Client App without setting redirect uri in the dashboard?
I know setting up client type from web to others or application may solve this issue. But I want to implement it for web type only. Is this possible?
<!DOCTYPE html>
<html>
<head>
<script>
'use strict';
var GO2 = function GO2(options) {
if (!options || !options.clientId) {
throw 'You need to at least set the clientId';
}
if (typeof window != 'undefined'){
this._redirectUri = window.location.href.substr(0,
window.location.href.length -
window.location.hash.length)
.replace(/#$/, '');
}
// Save the client id
this._clientId = options.clientId;
// if scope is an array, convert it into a string.
if (options.scope) {
this._scope = Array.isArray(options.scope) ?
options.scope.join(' ') :
options.scope;
}
// rewrite redirect_uri
if (options.redirectUri) {
this._redirectUri = options.redirectUri;
}
// popup dimensions
if (options.popupHeight) {
this._popupHeight = options.popupHeight;
}
if (options.popupWidth) {
this._popupWidth = options.popupWidth;
}
if (options.responseType) {
this._responseType = options.responseType;
}
if (options.accessType) {
this._accessType = options.accessType;
}
};
GO2.receiveMessage = function GO2_receiveMessage() {
var go2;
if (window.opener && window.opener.__windowPendingGO2) {
go2 = window.opener.__windowPendingGO2;
}
if (window.parent && window.parent.__windowPendingGO2) {
go2 = window.parent.__windowPendingGO2;
}
var hash = window.location.hash;
if (go2 && hash.indexOf('access_token') !== -1) {
go2._handleMessage(
hash.replace(/^.*access_token=([^&]+).*$/, '$1'),
parseInt(hash.replace(/^.*expires_in=([^&]+).*$/, '$1'), 10),
hash.replace(/^.*state=go2_([^&]+).*$/, '$1')
);
}
if (go2 && window.location.search.indexOf('code=')) {
go2._handleMessage(
window.location.search.replace(/^.*code=([^&]+).*$/, '$1'),
null,
window.location.search.replace(/^.*state=go2_([^&]+).*$/, '$1')
);
}
if (go2 && window.location.search.indexOf('error=')) {
go2._handleMessage(false);
}
};
GO2.prototype = {
WINDOW_NAME: 'google_oauth2_login_popup',
OAUTH_URL: 'https://accounts.google.com/o/oauth2/v2/auth',
_clientId: undefined,
_scope: 'https://www.googleapis.com/auth/plus.me',
_redirectUri: '',
_popupWindow: null,
_immediateFrame: null,
_stateId: Math.random().toString(32).substr(2),
_accessToken: undefined,
_timer: undefined,
_popupWidth: 500,
_popupHeight: 400,
_responseType: 'token',
_accessType: 'online',
onlogin: null,
onlogout: null,
login: function go2_login(forceApprovalPrompt, immediate) {
if (this._accessToken) {
return;
}
this._removePendingWindows();
window.__windowPendingGO2 = this;
var url = this.OAUTH_URL +
'?response_type=' + this._responseType +
'&access_type='+ encodeURIComponent(this._accessType) +
'&redirect_uri=' + encodeURIComponent(this._redirectUri) +
'&scope=' + encodeURIComponent(this._scope) +
'&state=go2_' + this._stateId +
'&client_id=' + encodeURIComponent(this._clientId);
console.log(url);
if (!immediate && forceApprovalPrompt) {
url += '&approval_prompt=force';
}
if (immediate) {
url += '&approval_prompt=auto';
// Open up an iframe to login
// We might not be able to hear any of the callback
// because of X-Frame-Options.
var immediateFrame =
this._immediateFrame = document.createElement('iframe');
immediateFrame.src = url;
immediateFrame.hidden = true;
immediateFrame.width = immediateFrame.height = 1;
immediateFrame.name = this.WINDOW_NAME;
document.body.appendChild(immediateFrame);
return;
}
// Open the popup
var left =
window.screenX + (window.outerWidth / 2) - (this._popupWidth / 2);
var top =
window.screenY + (window.outerHeight / 2) - (this._popupHeight / 2);
var windowFeatures = 'width=' + this._popupWidth +
',height=' + this._popupHeight +
',top=' + top +
',left=' + left +
',location=no,toolbar=no,menubar=no';
this._popupWindow = window.open(url, this.WINDOW_NAME, windowFeatures);
},
logout: function go2_logout() {
if (!this._accessToken) {
return;
}
this._removePendingWindows();
clearTimeout(this._timer);
this._accessToken = undefined;
if (this.onlogout) {
this.onlogout();
}
},
getAccessToken: function go2_getAccessToken() {
return this._accessToken;
},
// receive token from popup / frame
_handleMessage: function go2_handleMessage(token, expiresIn, stateId) {
if (this._stateId !== stateId) {
return;
}
this._removePendingWindows();
// Do nothing if there is no token received.
if (!token) {
return;
}
this._accessToken = token;
if (this.onlogin) {
this.onlogin(this._accessToken);
}
if (expiresIn) {
// Remove the token if timed out.
clearTimeout(this._timer);
this._timer = setTimeout(
function tokenTimeout() {
this._accessToken = undefined;
if (this.onlogout) {
this.onlogout();
}
}.bind(this),
expiresIn * 1000
);
}
},
destory: function go2_destory() {
if (this._timer) {
clearTimeout(this._timer);
}
this._removePendingWindows();
},
_removePendingWindows: function go2_removePendingWindows() {
if (this._immediateFrame) {
document.body.removeChild(this._immediateFrame);
this._immediateFrame = null;
}
if (this._popupWindow) {
this._popupWindow.close();
this._popupWindow = null;
}
if (window.__windowPendingGO2 === this) {
delete window.__windowPendingGO2;
}
}
};
// if the context is the browser
if (typeof window !== 'undefined') {
// If the script loads in a popup matches the WINDOW_NAME,
// we need to handle the request instead.
if (window.name === GO2.prototype.WINDOW_NAME) {
GO2.receiveMessage();
}
}
// Expose the library as an AMD module
if (typeof define === 'function' && define.amd) {
define('google-oauth2-web-client', [], function () { return GO2; });
} else if (typeof module === 'object' && typeof require === 'function') {
// export GO2 in Node.js, assuming we are being browserify'd.
module.exports = GO2;
if (require.main === module) {
console.error('Error: GO2 is not meant to be executed directly.');
}
} else {
window.GO2 = GO2;
}
function test(){
var go2 = new GO2({
clientId: 'dfsdffdfgsfsdfggdgd.apps.googleusercontent.com',
redirectUri: 'http://localhost:8888/gapi/test.html',
responseType: 'code',
accessType: 'offline'
});
go2.login();
}
</script>
</head>
<body>
<a href='#' onClick='test();'> Click here to login </a>
</body>
</html>
It looks like you're using the implicit grant type which requires a redirect uri with response_type=token.
Can you use the authorization code grant type?
The redirect uri is optional for the authorization code grant type.
https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
This is the scenario I want:
I'm checking for the presence of an application (using protocol detection), if it's not present the exe file automatically starts downloading. The webpage continuously checks in regular interval whether the app has been successfully downloaded and when the installation is complete, the browser prompts to open the app.
What is working:
The download is starting automatically. The webpage is checking for the presence of the app in regular interval.
What is NOT working:
After the exe is downloaded, when I start the download, the focus shifts and the webpage thinks that the app has been launched, whereas the app actually hasn't yet been installed even.
I need a focus checking mechanism which detects when the specific app has been launched and focus shifts and not respond to any other focus shifts.
This is my code:
_registerEvent = function(target, eventType, cb) {
if (target.addEventListener) {
target.addEventListener(eventType, cb);
return {
remove: function() {
target.removeEventListener(eventType, cb);
}
};
} else {
target.attachEvent(eventType, cb);
return {
remove: function() {
target.detachEvent(eventType, cb);
}
};
}
},
checkIfHasProtocol = function($el) {
openUriWithTimeoutHack(url);
},
openUriWithTimeoutHack = function(protocol) {
var timeout = setTimeout(function() {
handler.remove();
checkIfHasProtocol(protocol);
}, 5000);
var target = window;
while (target != target.parent) {
target = target.parent;
}
var handler = _registerEvent(window, "blur", onBlur);
function onBlur() {
if (tabVisible() && isBlurred) {
clearTimeout(timeout);
handler.remove();
//App has been launched
}
}
}
window.location = protocol;
};
tabVisible(function() {
if (tabVisible() && inCheck) {
inCheck = false;
}
});
window.addEventListener("blur", function() {
isBlurred = true;
});
window.addEventListener("focus", function() {
isBlurred = false;
inCheck = false;
});
I'm currently trying to make push notification working for dev/production environment through Appcelerator Platform.
I created my push certificates (dev/prod) on apple developer platform, I exported it to .p12 file, and uploaded it on my ArrowDB iOS Push configuration. My Titanium app and my ArrowDB seems correctly linked (good keys for production and developpement).
From my app, I get device token, I get a successfull return from subscribing to notifications, and I can see from Appcelerator that I have one ios device linked.
When I send push notification from Appcelerator ArrowDB platform, I don't receive anything while Appcelerator logs shows a Successful push.
My code for ACS Notification handling :
var Cloud = require('ti.cloud');
var ANDROID = Ti.Platform.name === 'android';
var IOS = !ANDROID && (Ti.Platform.name === 'iPhone OS');
var BLACKBERRY = !ANDROID && !IOS && (Ti.Platform.name === 'blackberry');
Cloud.debug = true; // optional; if you add this line, set it to false for production
var deviceToken = null;
// Check if the device is running iOS 8 or later
if (Ti.Platform.name == "iPhone OS" && parseInt(Ti.Platform.version.split(".")[0]) >= 8) {
// Wait for user settings to be registered before registering for push notifications
Ti.App.iOS.addEventListener('usernotificationsettings', function registerForPush() {
// Remove event listener once registered for push notifications
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
Ti.Network.registerForPushNotifications({
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
});
// Register notification types to use
Ti.App.iOS.registerUserNotificationSettings({
types: [
Ti.App.iOS.USER_NOTIFICATION_TYPE_ALERT,
Ti.App.iOS.USER_NOTIFICATION_TYPE_SOUND,
Ti.App.iOS.USER_NOTIFICATION_TYPE_BADGE
]
});
}
// For iOS 7 and earlier
else {
Ti.Network.registerForPushNotifications({
// Specifies which notifications to receive
types: [
Ti.Network.NOTIFICATION_TYPE_BADGE,
Ti.Network.NOTIFICATION_TYPE_ALERT,
Ti.Network.NOTIFICATION_TYPE_SOUND
],
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
}
// Process incoming push notifications
function receivePush(e) {
console.log('Received push: ' + JSON.stringify(e));
alert('Received push: ' + JSON.stringify(e));
}
// Save the device token for subsequent API calls
function deviceTokenSuccess(e) {
deviceToken = e.deviceToken;
}
function deviceTokenError(e) {
alert('Failed to register for push notifications! ' + e.error);
}
function ACSPush(acsuid, acspwd) {
this.acsuid = acsuid || false;
this.acspwd = acspwd || false;
}
ACSPush.prototype.registerDevice = function(channel_name, onReceive, onLaunched, onFocused, androidOptions, iosOptions, blackberryOptions) {
var that = this,
token = '';
function deviceTokenSuccess(e) {
console.log('Device Token: ' + e.deviceToken);
token = e.deviceToken;
that.token = token;
loginToACS(that.acsuid, that.acspwd, token, channel_name);
}
function deviceTokenError(e) {
console.log('Token Error: ' + e.error);
}
function receivePush(e) {
onReceive(e.data);
console.log("push notification received: " + JSON.stringify(e.data));
}
if (ANDROID) {
var CloudPush = require('ti.cloudpush');
CloudPush.retrieveDeviceToken({
success : deviceTokenSuccess,
error : deviceTokenError
});
CloudPush.focusAppOnPush = androidOptions.focusAppOnPush || false;
CloudPush.showAppOnTrayClick = androidOptions.showAppOnTrayClick || false;
CloudPush.showTrayNotification = androidOptions.showTrayNotification || false;
CloudPush.showTrayNotificationsWhenFocused = androidOptions.showTrayNotificationsWhenFocused || false;
CloudPush.singleCallback = androidOptions.singleCallback || true;
CloudPush.addEventListener('callback', onReceive);
CloudPush.addEventListener('trayClickLaunchedApp', onLaunched);
CloudPush.addEventListener('trayClickFocusedApp', onFocused);
} else if (IOS) {
// Check if the device is running iOS 8 or later
if (parseInt(Ti.Platform.version.split(".")[0]) >= 8) {
function registerForPush() {
Ti.Network.registerForPushNotifications({
success : deviceTokenSuccess,
error : deviceTokenError,
callback : receivePush
});
// Remove event listener once registered for push notifications
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
};
// Wait for user settings to be registered before registering for push notifications
Ti.App.iOS.addEventListener('usernotificationsettings', registerForPush);
// Register notification types to use
Ti.App.iOS.registerUserNotificationSettings({
types : iosOptions.types,
categories : iosOptions.categories
});
} else {
// For iOS 7 and earlier
Ti.Network.registerForPushNotifications({
// Specifies which notifications to receive
types : iosOptions.types,
success : deviceTokenSuccess,
error : deviceTokenError,
callback : receivePush
});
}
} else if (BLACKBERRY) {
Ti.BlackBerry.createPushService({
appId : blackberryOptions.appId,
ppgUrl : blackberryOptions.ppgUrl,
usePublicPpg : blackberryOptions.usePublicPpg,
launchApplicationOnPush : blackberryOptions.launchApplicationOnPush,
onSessionCreated : function(e) {
console.log('Session Created');
},
onChannelCreated : function(e) {
console.log('Channel Created\nMessage: ' + e.message + '\nToken: ' + e.token);
token = e.token;
that.token = token;
console.log("Device Token: " + token);
loginToACS(that.acsuid, that.acspwd, token, channel_name);
},
onPushReceived : function(e) {
onReceive(e.data);
e.source.removeAllPushes();
},
onConfigError : function(e) {
console.log('ERROR\nTitle: ' + e.errorTitle + +'\nMsg: ' + e.errorMessage);
},
onError : function(e) {
console.log('ERROR\nTitle: ' + e.errorTitle + +'\nMsg: ' + e.errorMessage);
},
onAppOpened : function(e) {
onLaunched(e.data);
e.source.removePush(e.pushId);
}
});
} else {
alert("Push notification not implemented yet into acspushmod for " + Ti.Platform.osname);
}
};
ACSPush.prototype.unsubscribeFromChannel = function(channel_name, token, onSuccess, onFail) {
var that = this;
Cloud.PushNotifications.unsubscribe({
channel : channel_name,
device_token : token
}, function(e) {
if (e.success) {
onSuccess(e);
} else {
onFail(e);
}
});
};
ACSPush.prototype.getToken = function() {
return this.token;
};
function loginToACS(acsuid, acspwd, token, channel_name) {
if (!acsuid && !acspwd) {
console.log("loginToACS -> subscribe as guest");
subscribeForPushNotifications(token, channel_name, true);
return;
}
Cloud.Users.login({
login : acsuid,
password : acspwd
}, function(e) {
if (e.success) {
var user = e.users[0];
console.log("loginToACS -> Status: Successful");
subscribeForPushNotifications(token, channel_name);
} else {
console.log('acsuid = ' + acsuid + " acspwd = " + acspwd);
console.log("loginToACS -> Error :" + e.message);
}
});
};
function subscribeForPushNotifications(token, channel_name, subscribeAsGuest) {
var prams = {
channel : channel_name,
type : IOS ? 'ios' : Ti.Platform.osname, // osname return iphone / ipad on iOS
device_token : token
};
var callBack = function(e) {
if (e.success) {
console.log('subscribeForPushNotifications -> Status: Successful [' + channel_name + ']');
} else {
console.log('subscribeForPushNotifications -> Error ' + token + '(subscribeToServerPush) :\\n' + ((e.error && e.message) || JSON.stringify(e)));
}
};
if (subscribeAsGuest) {
Cloud.PushNotifications.subscribeToken(prams, callBack);
} else {
Cloud.PushNotifications.subscribe(prams, callBack);
}
};
And This code used to work before I change appcelerator account (migrating to my client account).
If you guys have any idea of what am I doing wrong, I will be very thankful.
Thanks a lot !
Environment : Appcelerator studio, Titanium SDK 5.0.0.GA, iphone5S
I'm using Sencha Touch 2.3.1 and using a list defined like this :
{
xtype: 'list',
id: 'index_list',
infinite: true,
flex: 1,
scrollToTopOnRefresh: false,
disableSelection: true,
store: 'store_index'
}
List's store has got more than 300 records, that's why I put the flag "infinite" to true.
Problem is when I scroll very fastly up and down through the list, app freezes and I can't do anything else with UI.
Also tested, put infinite flag to false doesn't fix it.
Cannot reproduce if data are less than ~300 records.
Platforms : iOS 6, 7 (iPhone), not iPad.
Have you got any idea ?
Use this override works for me
Ext.define('InfiniteListScroll.override.TouchGesture', {
override: 'Ext.event.publisher.TouchGesture',
lastEventType: null,
changedTouchesId: null,
lastEventObject: null,
onEvent: function(e) {
console.log('InfiniteListScroll.override.TouchGesture - onEvent');
var type = e.type,
lastEventType = this.lastEventType,
touchList = [e];
if ( type == 'touchstart' ) {
if( this.changedTouchesId == null ) {
this.changedTouchesId = e.changedTouches[0].identifier;
this.lastEventObject = e;
}
else {
console.log('changedTouchesId NOT null, touchEnd event wasnt fired for corresponding touchStart event.');
this.onTouchEnd( this.lastEventObject );
}
}
if (this.eventProcessors[type]) {
this.eventProcessors[type].call(this, e);
return;
}
if ('button' in e && e.button > 0) {
return;
}
else {
// Temporary fix for a recent Chrome bugs where events don't seem to bubble up to document
// when the element is being animated with webkit-transition (2 mousedowns without any mouseup)
if (type === 'mousedown' && lastEventType && lastEventType !== 'mouseup') {
var fixedEvent = document.createEvent("MouseEvent");
fixedEvent.initMouseEvent('mouseup', e.bubbles, e.cancelable,
document.defaultView, e.detail, e.screenX, e.screenY, e.clientX,
e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.metaKey,
e.button, e.relatedTarget);
this.onEvent(fixedEvent);
}
if (type !== 'mousemove') {
this.lastEventType = type;
}
e.identifier = 1;
e.touches = (type !== 'mouseup') ? touchList : [];
e.targetTouches = (type !== 'mouseup') ? touchList : [];
e.changedTouches = touchList;
this.eventProcessors[this.mouseToTouchMap[type]].call(this, e);
}
},
onTouchEnd: function(e) {
console.log('InfiniteListScroll.override.TouchGesture - onTouchEnd');
if (!this.isStarted) {
return;
}
if (this.lastMoveEvent) {
this.onAnimationFrame();
}
var touchesMap = this.touchesMap,
currentIdentifiers = this.currentIdentifiers,
changedTouches = e.changedTouches,
ln = changedTouches.length,
identifier, i, touch;
this.changedTouchesId = null;
this.updateTouches(changedTouches);
changedTouches = e.changedTouches;
for (i = 0; i < ln; i++) {
Ext.Array.remove(currentIdentifiers, changedTouches[i].identifier);
}
e = this.factoryEvent(e);
for (i = 0; i < ln; i++) {
identifier = changedTouches[i].identifier;
touch = touchesMap[identifier];
delete touchesMap[identifier];
this.publish('touchend', touch.targets, e, {touch: touch});
}
this.invokeRecognizers('onTouchEnd', e);
// Only one touch currently active, and we're ending that one. So currentTouches should be 0 and clear the touchMap.
// This resolves an issue in iOS where it can sometimes not report a touchend/touchcancel
if (e.touches.length === 1 && currentIdentifiers.length) {
currentIdentifiers.length = 0;
this.touchesMap = {};
}
if (currentIdentifiers.length === 0) {
this.isStarted = false;
this.invokeRecognizers('onEnd', e);
if (this.animationQueued) {
this.animationQueued = false;
Ext.AnimationQueue.stop('onAnimationFrame', this);
}
}
}
});
I'm using the Ti.Storekit module and I have a problem. I can't use it, well, this is my code:
Storekit.requestProducts(['com.rotary.imrotarian.upgradeyears1', 'com.rotary.imrotarian.upgradeyears2'], function (evt) {
if (!evt.success) {
alert('ERROR: We failed to talk to Apple!');
}
else if (evt.invalid) {
alert('ERROR: We requested an invalid product!');
alert(evt);
}
else {
success(evt.products[0]);
success(evt.products[1]);
var dialog = Titanium.UI.createOptionDialog({
title: APP.L('inapp_purchase_store_name'),
options: [product1.title + ' - ' + product1.formattedPrice, product2.title + ' - ' + product2.formattedPrice, APP.L('Cancel')],
cancel:3
});
dialog.show();
dialog.addEventListener('click',function(e)
{
if (e.index == 0)
{
purchaseProduct(product1);
}
if (e.index == 1)
{
purchaseProduct(product2);
}
});
}
});
And when I use it it's not an apple error, it's an evt error.
If I print evt alert is like this:
{
invalid= {
"com.rotary.imrotarian.upgradeyears1",
"com.rotary.imrotarian.upgradeyears2"
};
products = {
};
source = "[object TiStorekitProductRequest]";
success = 1;
type = callback;
}
}
The purchaseProduct function is this:
function purchaseProduct(product) {
Ti.API.info('----- CALL APPLE PURCHASE ' + JSON.stringify(product.identifier));
Storekit.purchase(product, 1, function (evt) {
Ti.API.info('----- Apple answer purchase: ' + JSON.stringify(evt));
switch (evt.state) {
case Storekit.FAILED:
alert(APP.L('inapp_purchase_store_error_buy_failed'));
break;
case Storekit.PURCHASED:
case Storekit.RESTORED:
//var receipt = Ti.Utils.base64encode(evt.receipt).text;
//Ti.App.Properties.setString('recibo', receipt);
alert(APP.L('inapp_purchase_store_recipt_verified'));
markProductAsPurchased(product.identifier);
break;
}
});
};
Dunno what I'm doing wrong? But it seems like it doesn't detect this products.
Hope anyone can help me
Thanks.