here's my situation. I have a html +css + jquery well working project that I want to adapt in titanium. This project has geolocation + fb api call.
I want to adapt my project into a titanium html5 project. What I found is that I can call titanium api only through addEventListener and fireEvent functions (of course only if I use webviews).
it' my first titanium project I work with that needs geolocation and facebook api.
actually, I started to modify the previous project by adding addEventlistener into the app.js file and fireEvents into the javascript files of the previous project ( included in the first project in the html files) in the parts that need the titanium api calls (I can't call titanium api outside of app.js).
the problem is that I need some values (objects) to be returned back.
to better understand what I'm doing, here's the sequence of the events.
TITANIUM PROJECT
(app.js)
var win = Ti.UI.createWindow();
var webview = Ti.UI.createWebView({
url: 'index.html'
});
Ti.App.addEventListener('geolocation',function(){
//some titanium api call
lat = x;lon=y;
Ti.App.fireEvent('geolocation_back',{latitude:lat,longitude:lon});
});
win.add(webview);
win.open();
HTML + CSS + JS PROJECT
(imported file into index.html, not imported into app.js)
Ti.App.fireEvent('geolocation');
var my_lat ;
var my_lon ;
Ti.App.addEventListener('geolocation_back',function(d){
my_lat = d.latitude;
my_lon = d.longitude;
//do other stuff with my_lat and my_lon
});
I hope you understand what I'm doing.
my questions are:
1) is what I am doing the correct way to work with titanium and html code?
2) is there anyother way to call titanium api within html code and return variables/objects back?
EDIT
this code works only on iOS and android but not on web browser. it seems that the built in server (Titanium studio or Android web browser emulator) doesn't load the Ti.* or Titanium.* objects. is there anyway to make it works on web browser?
I see the web mobile compiler creates all the titanium API in subfolders
there is titanium.js and TI/* folder. can anyone explains me why the console says me Ti is not defined?
as I said here
I found a solution!
simply add to all of your html pages the simple script below
var Ti = window.parent.Ti
have fun!
Related
I want to get contact list from Android(If user open website in android). I was searching on it little bit. I found two question in stackoverflow similar to this.
Obtain Contacts Permission before Navigating (Cordova)
Listing phone contacts using javascript
Cordova
Here what I tried.
function onSuccess(contacts) {
alert('Found ' + contacts.length + ' contacts.');
};
function onError(contactError) {
alert('onError!');
};
// find all contacts with 'Bob' in any name field
var options = new ContactFindOptions();
options.filter = "Bob";
options.multiple = true;
options.desiredFields = [navigator.contacts.fieldType.id];
options.hasPhoneNumber = true;
var fields = [navigator.contacts.fieldType.displayName, navigator.contacts.fieldType.name];
navigator.contacts.find(fields, onSuccess, onError, options);
I didn't get any error or alert message in android. When I visit the webpage in PC I got an error
Uncaught ReferenceError: ContactFindOptions is not defined
at contacts.php:17
I think I am having error cause, there's no contact function in PC.
I am so beginner in JS. I think Cordova must be installed in PC, I am not sure of the information also. If I have to than how can I install Cordova? I am using Debian Based Linux Distro. So, I tried
sudo apt-get install cordova
But,
E: Unable to locate package cordova
Are you building a mobile app with Cordova or are you just running your code in a website on Android?
If it’s just a website: you simply can’t do what you want since the browser doesn’t provide an interface to the contact list.
Unlike a Cordova app, which has access to the system APIs, among them the contact list API, JavaScript Code executed in a mobile browser, cannot access such APIs. The browser JS API simply provides no way.
JavaScript code run inside a Cordova/Capacitor mobile app however can Cordova APIs which bridge the mobile’s native API to JavaScript.
I am working on a hybrid tizen app(web + native service) for Samsung Gear Fit2 Pro. I want to create/setup a config from web ui app and save it into data path of the app so that the native service can load the config and use it.
I am trying to create a config.txt file from tizen web app at /opt/usr/apps/pkg-id/data. I've tried using filesystem API of tizen with proper privileges but it always shows those API functions are undefined. However, if I use resolve then file creation works only for some directories like documents. But I want to create a file if not exists in my app's data folder i.e. /opt/usr/apps/pkg-id/data or modify it if already exists. Relevant portion of my code that tries to write to a file in data folder is shown below.
Is there any way to do that? Or am I doing something wrong while using the file-system api?
function app_get_datapath() {
return "/opt/usr/apps/"+tizen.application.getCurrentApplication().appInfo.packageId+"/data/";
}
var fileHandleWrite = tizen.filesystem.openFile(app_get_datapath()+'config.txt', 'w');
fileHandleWrite.writeString(tizen.systeminfo.getCapability('http://tizen.org/system/tizenid'));
fileHandleWrite.close();
Here are the list of privileges:
I've tried using filesystem API of tizen with proper privileges but it always shows those API functions are undefined.
Samsung Gear Fit2 Pro does not support all new APIs. Probably you should refer to Tizen 3.0 API, but the API you use in code snippet is supported since Tizen 5.0
My second comment is that you should not use paths built 'by hand' via string concatenation as you do in app_get_datapath(). It is highly non-portable solution, which can NOT work on some devices. Instead I would suggest using built-in virtual root for getting your application private storage - wgt-private, which will automatically return valid path on a device (no matter what the device is).
Example (using only 3.0 API, for 5.0 it would be much easier):
(function createConfig() {
function writeConfig(file) {
file.openStream('w', function (stream) {
stream.write(tizen.systeminfo.getCapability('http://tizen.org/system/tizenid'));
stream.close();
console.log('All done!!')
})
}
tizen.filesystem.resolve("wgt-private/config.txt", function (file) {
console.log('Config file exists - overwrite');
writeConfig(file);
}, function (e) {
console.log('Config file does not exist - create');
tizen.filesystem.resolve("wgt-private", function (dir) {
var file = dir.createFile("config.txt");
console.log("Created file")
writeConfig(file);
});
});
})()
We have a web based jquery mobile app that records activity of a user. This app is long standing and in use at the moment, so re-writing the application is not an option unfortunatly.
The problem is that we are trying to get GPS location at certain points using the application.. But as it is running in an instance of chrome, the javascript will not record correctly when the phone is locked, or the chrome is minimised.
So to get around that we are writing an Ionic App with Cordova in order to get the GPS coordinates in the background, regardless of the state of the browser.
Currently, this is working great. The issue however is there are certain events in our javascript that require a specific 'type' associated to our GPS logging.
My question is: How do I actually hook onto this javascript event in CHROME from the GPS background ionic/cordova application.
What we have tried so far:
Finding the chrome localstorage via Ionic/Cordova and reading a value from that on a timer.
The issue with this is we can't find the location of the localstorage/cache.
From this question it says its here:
/data/data/com.android.chrome/cache
but we can't find/access it from our ionic app or file browser on the android
https://android.stackexchange.com/questions/85998/android-google-chrome-browser-cache-location
We have also looked for ways to hook the javascript events to fire something inside the other application but we are having no luck there either..
Apologies for the long post.. Its hard to explain. If you have any suggestions on alternative methods to do this kind of cross-application event firing from Chrome to Ionic/Cordova I would be greatly interested to hear your oppinion.
To fix this I created a 'stack' where I could push an object to an array that would be picked up by the cordova app using executeScript as follows:
In the inappbrowser site:
var stackName = stackN1
function addEventToStack(numid, type) {
var stackRow = { 'numb': numid, 'type': type};
var stack = localGet(stackName); //localstorage
if (!stack)
stack = StackInit();
stack.push(stackRow);
localStore(stackName, stack);
console.log('Added to stack ', stack);
return 'Row Added';
}
In the cordova application:
ref.executeScript(
{
code: 'localStorage.getItem("stackN1")'
},
function(rdObj) {
//Iterate and use rdObj here
}
I have this simple Titanium js script.
app.js
var win = Ti.UI.createWindow();
var webview = Ti.UI.createWebView({
url: 'logging.html'
});
webview.addEventListener('help',function(){
alert('help');
});
win.add(webview);
win.open();
logging.html
<html>
<body>
<a onclick="Ti.App.fireEvent('help')">Help</a>
</body>
</html>
when I click on the Help link, the console gives me Reference Error: Ti is not defined.
I also tried changing Ti with Titanium, but same error.
------------- EDIT ----------
this error comes only with web browser. iOS works perfectly. but
when titanium studio compiles the project for web mobile, I can see titanium.js and TI/* folder, so I guess it can't load Ti object. can anyone explain me why?
I found a solution!
simply add to all of your html pages the simple script below
var Ti = window.parent.Ti
have fun!
EDIT:
from sdk version 3.0.2GA on, I guess they fixed it. now it calls Ti sdk without that hack!**
First, change:
webview.addEventListener('help',function(){
alert('help');
});
To:
Ti.App.addEventListener('help',function(){
alert('help');
});
And second: Call "Ti.App.fireEvent()" without the final "s" in your HTML file.
after some tests, I found that the previous code works perfectly on iOS phisical device/simulator and Android.
it doesn't on android web browser emulator and normal mobile browser (Firefox as mobile web app)
so, it seems that Titanium api calls will never work on web browsers because of "normal javascript library doesn't have Titanium.* or Ti.*".
I used this and it worked
window.parent.TiApp.fireEvent
We've got a problem that only seems to show up on an iOS device, but seems to work fine on the simulator. Here's the problem...
Our iOS app is Hybrid (Cordova) with some views that are entirely native and others that are entirely web.
we'd like use the same sqlite db from both codebases.
In the web we are using the WebSQL api (not a cordova plugin), from the Native iOS side we're using FMDB.
The database is initially created from javascript and is placed in the App's Library Directory
4.x Dir <AppDir>/Library/WebKit/Databases/file__0/0000000000000001.db
5.x Dir <AppDir>/Library/Caches/file__0/0000000000000001.db
Whenever the sqlite database is accessed by FMDB, the JS code can no longer run transactions against the database it created.
While there are other similar SO questions out there, I have yet to see one where the DB was to be accessed by both the web and native. Based upon the research I've done so far, it seems this is a sandboxing issue that only shows up on the device. Here is the code we are using to open the database.
NSArray *libraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
NSUserDomainMask,
YES);
NSString *libraryDir = [libraryPaths objectAtIndex:0];
NSString *databasePath = [libraryDir
stringByAppendingPathComponent:#"WebKit/Databases/file__0/"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:databasePath]) {
databasePath = [libraryDir
stringByAppendingPathComponent:#"Caches/file__0/"];
}
NSString *databaseFile = [databasePath
stringByAppendingPathComponent:#"0000000000000001.db"];
if (!static_fmdb) {
static_fmdb = [FMDatabase databaseWithPath:databaseFile];
NSAssert(static_fmdb, #"Unable to open create FMDatabase");
}
if (![static_fmdb open]) {
NSLog(#"Error in %#: Failed to connect to database!\n",
NSStringFromSelector(_cmd));
}
Note that after this code runs, subsequent calls to the database from the JS side result in the following error:
"unable to open a transaction to the database"
We were able to get to the desired result here by rolling back migrations on our sqlite database all the way back to before the first migration, effectively giving us a clean database. We also did not delete any of the cache files created by the web view. Its not the worlds best solution, but it seems to work for our use case. If there are any other answers out there, I'd love to hear more about them.