Codenameone: AppArg is null on ios when app open via applink - codenameone

When opening my ios app via an applink, as specified by associated domains feature, the AppArg is null.
The consecutive call of start() method, as described in this issue, does not occur.
In my case, start() is called only once, with a null AppArg, and that's it.
The first thing a do, in the start() method, is call
Display.getInstance().getProperty("AppArg",null);
This works fine when opening the app via a custom scheme, but not when opening via an applink.
Note: I use the ios.glAppDelegateBody and ios.afterFinishLaunching build hints to handle app open via push notification. I figured this might interfere with AppArg reading so I removed those temporarily and tried again, but to no avail.
Currently, the only solution I see is to write some native code and try to get the opening url this way, but I'd very much like for the AppArg to work as it states.
I've tested on iphone 6s with ios 15.1.
Update 3:
This problem occurs due to the call of the facebook sdk in the didFinishLaunchingWithOptions which causes the method to return NO, and that prevents continueUserActivity to execute and retrieve the launch url. The offending code is this:
return [[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
This code gets executed if the facebook.appIdbuild hint is present in the codenameone settings.
After I removed it, things started working.
However, you won't be able to do this if you actually use facebook connect.
Update 2
I added the following snippet to the apple-app-site-association file hosted on my domain, as per the documentation here.
"activitycontinuation": {
"apps": [ <id of my app> ]
}
It didn't work still.
The same documentation also states the an associated domain entitlement like this: activitycontinuation:example.com should be added. So I added it to the ios.associatedDomains build hint, along with the applinks, looking like this:
ios.associatedDomains=applinks:mydomain.com,activitycontinuation:mydomain.com
It still didn't work. The build suceeded, but I'm not sure that codename one is actually doing something with activitycontinuation service.
So, the problem is still not solved!
Update:
So, the flow start,stop,start only happens when the app is in background and gets opened via an applink click, and both times start is called with the AppArg populated with the applink. All well in this case.
However, if the app is closed, and opepend via applink click, start is called only once and the AppArg is null. Problem!
The method shouldApplicationHandleURL is never called. I implemented it on the main app class, returning true.
I have also tried adding native code to try to get the applink, for the case when the app was previously closed. I tried to add the code below to the glAppDelegateBody build hint, but the build failed complaining that the continueUserActivity is duplicate. The code used was something like this:
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
NSURL *url = userActivity.webpageURL;
// Handle url
return YES;
}
Currently, I'm running out of ideas. So, please, help. Thank you.

iOS uses a different mechanism for dealing with applinks than it does for custom app URL schemes, so it is likely that there is a race condition here -where start() is being called before the URL is provided to the app.
Try implementing the com.codename1.system.URLCallback interface in your main lifecycle class and implement the shouldApplicationHandleURL method. This should be called when an applink is processed.

The solution, in my case, was to remove the facebook.appId build hint from the condenameone_settings.properties. I wasn't using facebook anymore, but forgot about the build hint. After removing it, things started working.
Found about this here.

By adding the following code to the ios.afterFinishLaunching build hint, the AppArg will be populated at start with the app launchUrl (if any), regardless of the fact that facebook sdk is used or not:
NSDictionary *activityDictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsUserActivityDictionaryKey];
if (activityDictionary) {
NSUserActivity *userActivity = [activityDictionary valueForKey:#"UIApplicationLaunchOptionsUserActivityKey"];
if (userActivity != nil) {
if ([NSUserActivityTypeBrowsingWeb isEqualToString:userActivity.activityType] && userActivity.webpageURL != nil) {
JAVA_OBJECT launchUrlStr = fromNSString(CN1_THREAD_GET_STATE_PASS_ARG [userActivity.webpageURL absoluteString]);
JAVA_OBJECT appArgKey = fromNSString(CN1_THREAD_GET_STATE_PASS_ARG #"AppArg");
JAVA_OBJECT displayInstObj = com_codename1_ui_Display_getInstance__(CN1_THREAD_GET_STATE_PASS_SINGLE_ARG);
com_codename1_ui_Display_setProperty___java_lang_String_java_lang_String(CN1_THREAD_GET_STATE_PASS_ARG displayInstObj, appArgKey, launchUrlStr);
}
}
}

Related

Error on Laravel 4 production: Call to undefined method Illuminate\Database\QueryException::message()

I'm managed to set up a L4 project on to a sub directory:
http://secure.myultratrust.com/test/users/create#b
I have it on a subdomain too:
http://test3-l4.ultratrust.com/users/create#b
I get this error on submitting:
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Call to undefined method Illuminate\Database\QueryException::message()
(BTW, ignore the #b at the end of the URL. I'm using a backbutton javascript functionality called backb). =)
Both have the exact same message. I have it completely working on my local environment. I thought it may be the database settings so I tested the database on another test file (not connected to the l4 app) to see if the db settings were corret. The db connections work but again the test connect file isn't using l4.
The l4 route seems to be working for, at least, getting to blade views to show. However, the form submissions aren't working. I was trying to get my PHPStorm to step through but I can't get it to work right now so I find it's hard to track down this problem. =(
So what could be the problem? Any help is much appreciated!
Thanks and have a blessed day<><,
Victor
Replace message() with getMessage(). So your line 116 on UsersController.php should read like this:
$error = $e->getMessage();
This should fix the particular error. However since the PDException is being thrown, it should cause another exception which will then show to the screen to enable further debugging.
How did I figure this out? the $e variable is an instance of PDOException. If you look at the public API for this class, you find that there is no method called message() you can call. However this is getMessage() and that's probably what you meant to do in the first place. Access the public API here:
http://php.net/manual/en/class.pdoexception.php

Close method not working in Office

Im trying to use Microsoft.Office.Interop.Word._Document.Close() in a .net 3.5 windows form app.
No matter how much I search here and on Google I cannot find the correct parameters to put in the Close method.
I am using version 14.0.0.0 of Microsoft.Office.Interop.Word and I would like to close the document without saving and ideally ensure that the application can isolate the document thread so that users can still open word documents outside the running application.
See the Close method of the Document class described in MSDN. If you need to omit the parameter and use the default value - pass the Type.Missing parameter.
Try this:
object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
object missing = System.Reflection.Missing.Value;
_Document.Close(ref doNotSaveChanges, ref missing, ref missing);
This is the source
I'm not sure if you'll need the middle line or not. It's not from the original source it's from here

How to list all datasets in CKAN (not only the active ones)

I am working on a project based on CKAN, and I am required to list in a page all the datasets that have the state "active" and "draft". When you go to the datasets page, you can only see the ones that have the state marked as "active", but not "draft".
If I use the API (call the package_list() method) or REST calls (http://localhost/api/3/action/package_list), CKAN only returns "active" datasets, but not "drafts". I double and triple checked the documentation, and apparently one cannot lists the datasets by their state.
Does anybody have a clue on how to do this? Has anybody done this already?
Thanks!
If nothing else, you could write an extension to do this. The database call itself will be pretty simple:
SELECT id,title,name FROM package WHERE state='active' OR state='draft';
I managed to modify CKAN core to list the datasets that do not have the state "draft" or "deleted", and it works, but I do no want to touch CKAN's core, I want to do this using a plugin, so the normal thing to do is to implement plugins.IActions and override the package_list method with a custom one. I have already written my own extension to try to modify CKAN behavior on method package_list(), but I can't seem to figure it out how to make it work.
Here is my code:
#side_effect_free
def package_list_custom(context, data_dict=None):
datasets = []
dataset_q = (model.Session.query(model.Package)
.join(model.PackageRole))
for dataset in dataset_q:
if dataset.state != 'draft' and dataset.state != 'deleted':
datasets.append(dataset)
return [dataset.id for dataset in datasets]
class Cnaf_WorkflowPlugin(plugins.SingletonPlugin):
plugins.implements(plugins.IActions)
def get_actions(self):
return {
'package_list' : package_list_custom
}
If I modify CKAN core it works very well, but the problem is that I am not to touch it, so I am obliged to do it via an extension.
EDIT: Ok, I managed to make it work, you need to decorate the method with #side_effect_free. I modified my code, and now it works.
The package_search API is capable of this, by searching for state:draft and setting the include_drafts=True flag. Something like this:
https://my-site.com/api/action/package_search?q=state:draft&include_drafts=True
You should be able to access this from a plugin with something like: ckan.plugins.toolkit.get_action('package_search')(context=context, data_dict={'q': 'state:draft', 'include_drafts': True}) (you'll need to assemble the context yourself, containing a 'user' key for the current username and a 'userobj' key for the current user object).
Then make a page from the results.

adding controller later

I'm trying to create an NG app where parts can be enabled/disabled dynamically. The idea is to have an "admin" page, where parts of the app can be enabled or disabled, and then see new functionality appear, in the form of an adjusted menu at the top of the page, and matching routes, controllers, etc loaded into the app (I'm using SocketStream w/ NG).
The first step was to add / remove routes dynamically, for which I found a solution at https://stackoverflow.com/a/13173667 - working well, as far as I can tell.
Next, adding items to the menu bar - easy with ng-repeat on ul/li items.
So the app adjusts its menu and recognizes the corresponding route. So far so good.
The problem comes with registering a controller. I'm calling myApp.controller('SandboxCtrl',[...]) with proper args (same as what worked when initialising statically on startup), but the controller does not appear to get loaded or inited properly. Navigating to the newly added route generates errors such as:
Error: Argument 'SandboxCtrl' is not a function, got undefined
assertArg#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:973
assertArgFn#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:984
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:4638
update#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:14007
$broadcast#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:8098
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7258
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6695
$eval#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7848
$digest#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7713
$apply#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7934
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:5433
I'm currently at a loss on how to proceed. I've not been able to find a solution on the web. The app is too large to put in a jsFiddle, but I can commit the last changes on GitHub if needed.
Questions: is this feasible? what can I do to debug this? any examples I could look at?
EDIT: The code is now at https://github.com/jcw/housemon (needs node/npm/redis). It's easy to reproduce the problem: launch with "npm start", browse to localhost:3333, go to admin tab, click on "jcw-sandbox" and then "Install". Top menu will update with new a "Sandbox" entry. Clicking on that entry generates the error shown above.
Oh, almost forgot: relevant code is in client/code/app/main.coffee and client/code/modules/routes.coffee ...
The answer turns out to be two-fold:
the NG calls were made from SocketStream RPC callbacks, and had to be wrapped in $scope.$apply calls - my bad, didn't know about this SS/NG interaction
the rest of the solution was outlined by #matys84pl - pick up $controllerProvider (and $filterProvider) early on, so they can be called at a later time instead of the normal "app.controller" and "app.filter" members, which don't seem to work anymore later on
Example code in GitHub, I'll link to a specific commit so this answer stays valid:
https://github.com/jcw/housemon/commit/f199ff70e3000dbf57836f0cbcbb3306c31279de

HTML Bridge not working with cross-domain Silverlight XAP

I've got a complex Silverlight app that uses the HTML bridge functionality quite extensively (in both directions). The app runs fine when the hosting page is from the same domain as the XAP source. Unfortunately, I can't get the HTML bridge functionality to work when the hosting page is on a different domain.
Now, I know the various tricks normally required to get this to work, i.e., everything that's documented here: http://msdn.microsoft.com/en-us/library/cc645023(VS.95).aspx. I've even put together my own simplified cross-domain repro that I was hoping would highlight the problem, but unfortunately, my "repro" works, i.e., both JS->SL and SL->JS functionality work just fine in it, even if the XAP is hosted on a different domain.
Here's what I've tried so far to narrow down the problem:
On my production solution (where I'm having the problem):
Confirmed that "EnableHtmlAccess" is set to true in the <object> tag.
Confirmed that "ExternalCallersFromCrossDomain" is set to "ScriptableOnly" in the AppManifest.xml file.
On my repro solution (where I can't get it to have the problem):
Added multiple libraries with multiple registered scriptable objects.
Added events to the registered objects.
On both:
Tried it with a static <object> tag and with a dynamically created <object> tag (via Silverlight.js).
Tried it with and without specifying handlers for onSourceDownloadProgressChanged, onSourceDownloadComplete, onError, and onLoad.
Tried it with and without a splashscreen.
I'm kinda running out of ideas. Anyone have any suggestions for other troubleshooting steps?
Well, so far I haven't been able to track down the precise difference between the working and the non-working versions. But I came up with a workaround that's sufficient for my needs. As it turns out, only the JS->SL functionality was broken; any calls from SL->JS still worked. So what I did was to register the scriptable SL objects from within Silverlight. In my controlling JavaScript class, I created a function with a unique name, and registered it with the window object:
var mLoadingController;
var mAppId = 'alantaClient_' + Alanta.makeId();
var mSetLoadingControllerId = mAppId + '_SetLoadingController';
window[mSetLoadingControllerId] = function (value) {
mLoadingController = value;
onLoad();
};
And then I pass in the name of the function as a part of the Silverlight app's InitParams:
var initParams = 'setLoadingControllerId=' + mSetLoadingControllerId;
Silverlight.createObject(mSource, mAppHost, mAppId, params, events, initParams);
And then I call that registration function from within Silverlight, like so:
// Do everything necessary to make the LoadingController scriptable.
HtmlPage.RegisterScriptableObject("LoadingController", LoadingController.Instance);
string setLoadingControllerId;
if (e.InitParams.TryGetValue(LoaderConstants.SetLoadingControllerIdReference, out setLoadingControllerId))
{
HtmlPage.Window.Invoke(setLoadingControllerId, LoadingController.Instance);
}
And then I can call it from JS, like so:
mLoadingController.GoToRoom();
Kinda hacky, but it works. Close enough for now.

Resources