Same Titanium code base for Android & Iphone - android

I have been trying to create a single codebase for both Iphone & Android for a intermediate level app. ( 4 tabs, multiple windows, maps etc.) using itanium 2.1 API.
However, I have found that things on Android platform dont work as smoothly or willingly as on Iphone epsecially tableviews & UI elemnts. The UI responsiveness on Android is also sluggish.
The kitchen sink examples are pretty straightforward. I am looking at an enterprise ready app which has to be maintained for atleast next couple of years.
Has anybody worked on similar lines with platform quirks and been successful in creating fully functional iOS & Android apps from SAME codebase?

I'm having a lot of success using the compile-time CommonJS mechanism for having a root view that then has os-specific capabilities.
For instance, my os-independent view might be ui/MyView.js :
var createAddButton = require("ui/MyView.AddButton");
var MyView = function() {
var self = Ti.UI.createWindow();
createAddButton(self, function() { alert('ADD!'); });
return self;
};
module.exports = MyView;
Then, I create os-specific functions to handle it:
iphone/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
var addButton = Titanium.UI.createButton({
systemButton: Titanium.UI.iPhone.SystemButton.ADD
});
addButton.addEventListener("click", addHandler);
view.rightNavButton = addButton;
};
android/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
view.activity.onCreateOptionsMenu = function(e){
var menuItem = e.menu.add({ title: "Add" });
menuItem.addEventListener("click", addHandler);
};
};
The CommonJS system they have implemented will pick the appropriate version of MyView.AddButton.js so that the button is added to the right place. It allows for the majority of the view to be the same, but the os-specific things to be separated properly.

Titanium is not meant for 1 codebase for all. You do need to rewrite stuff for every OS. However, some app developers claim to have reused 95% of its code. So only 5% of the code is OS specific. But I am sure their code is full with if-elses.
What I recommend doing, to be able to maintain it properly, without thousands of if-else constructions, is build a single backend core, and write code specifically for UI related matters per OS. This way, you have some UI related code for Android, UI related code for iOS and 1 core working for both.
Since Android and iOS differ a lot, writing a single codebase will make sure you can never use OS specific features (like android hardware menu button, or iOS NavigationGroup), and will let the UI look non-intuitive.

Related

Using detox to look at UI in different orientations (Android)

So I am using detox to take screenshots of my app. I'm using a connected Android device. The device.takeScreenshot function works. Now what is the best way to see what my app looks like on different orientations? Is the only way to just change the tablet orientation and run the test again? Or is there a smarter way to do it?
I'm not entirely sure what you're asking here, but in order to change orientation you can use device.setOrientation().
Is the only way to just change the tablet orientation and run the test again?
To me, this sounds like two separate use cases (portrait vs. vertical). Would be easier to maintain.
Lastly, as far as screenshot testing is concerned, you might find the practices described in Detox's screenshots guide useful:
...
the concept is mainly useful for verifying the proper visual structure and layout of elements appearing on the device's screen, in the form of a snapshot-test. Namely, by following these conceptual steps:
Taking a screenshot, once, and manually verifying it, visually.
Storing it as an e2e-test asset (i.e. the snapshot).
Using it as the point-of-reference for comparison against screenshots taken in consequent tests, from that point on.
const fs = require('fs');
describe('Members area', () => {
const snapshottedImagePath = './e2e/assets/snapshotted-image.png';
it('should greet the member with an announcement', async () => {
const imagePath = (take screenshot from the device); // Discussed >below
expectBitmapsToBeEqual(imagePath, snapshottedImagePath);
});
});
function expectBitmapsToBeEqual(imagePath, expectedImagePath) {
const bitmapBuffer = fs.readFileSync(imagePath);
const expectedBitmapBuffer = fs.readFileSync(expectedImagePath);
if (!bitmapBuffer.equals(expectedBitmapBuffer)) {
throw new Error(`Expected image at ${imagePath} to be equal to image >at ${expectedImagePath}, but it was different!`);
}
}
Important: The recommended, more practical way of doing this, is by utilizing more advanced 3rd-party image snapshotting & comparison tools such as applitools.

Create and change to new view with React Native

We're currently working on an app for one of our customers, and we've decided to use React Native as the technology to use for creating the app.
I'm pretty new to this technology, and I'm used to developing apps with either C# or Java, where I have full-fledged IDEs that provide all the functionality I need.
I'm currently creating a login screen, and would like to change to different views, depending on the type of login (e.g.: Facebook, Google, Twitter, Email, etc.).
How do I go about doing this. As I mention, with an IDE, it'd be a shortcut like SHIFT+ALT+A or something to create a new item, select type, name it and the IDE does the rest.
Do I have to create a new xx.android/ios.js file, and somehow call that, or do I need to go in to the native backend of the different projects?
What I tried was something along the lines of:
class Class extends Component {
render() {
<UI code here>
<Button onPress={this.eventHandler}
}
eventHandler(event) {
var xxLogin = new xxLogin();
xxLogin.render();
}
}
class xxLogin extends Component {
render() {
<UI code here>
}
}
But that failed, which I expected.
Thanks in advance for any help!
P.S.: I'm using Mac OS X El Capitan, if that helps.

Generic mobile tests with appium

I'm new to mobile testing , and currently I research for an automation framework for mobile testing.
I've started to look into Appium, and created some tests for the demo app I've made (one for IOS and the other for Android).
I've managed to write a test for each of the platforms , but I was wondering , how difficult it might be to write a one generic test which will be executed on the both platforms with minimum adjustments ?
Thanks
It is possible but you have to keep same labels for each component for all platforms, for example to click on a button, instead of locating through Xpath locate by its name.
WebElement button = driver.findElement(By.name("my button")); button.click();
More info finding elements in Appium docs:
http://appium.wikia.com/wiki/Finding_Elements
I built an automation framework from scratch which does exactly the same thing, i.e. have one code base and the tests run both on Android and iOS based on what device and app you give the test. This is how I went about doing it. (I used Java+Appium+Cucumber framework).
Following the Page Object pattern is a good practice for writing automation code.
That being said, you will have all the resource ids of Android and Accessibility ids of iOS in 2 separate files under a folder named say "ObjectRepository". These files usually have the extension of *.properties (It is called the properties file).
Say you have a Login button that you want to interact with on Android and iOS, you have will 2 files:
File 1) "androidObject.properties" which has:
Login.LoginButton=loginAndroidBtn
File 2) "iOSObject.properties" which has:
Login.LoginButton=loginiOSBtn
NOTE: In the key/value pair above, the key is the same "Login.LoginButton", the value is the resource id and the accessibility id of the Login Button in your Android and iOS application
In your code you would do the following:
if(IS_ANDROID) {
DRIVER.findElementById("Login.LoginButton").click();
} else {
DRIVER.findElementByAccessibilityId("Login.LoginButton").click();
}
In another file you would set what IS_ANDROID and IS_IOS means. You may do something like this:
public static DeviceConfig DEVICE_CONFIG;
private void setPlatform() {
if (DEVICE_CONFIG.platformName.equals("Android")) {
IS_ANDROID = true;
} else if (DEVICE_CONFIG.platformName.equals("iOS")) {
IS_IOS = true;
}
This way you can have one code base and run Android and iOS seamlessly.

Using Cordova, is there a way to reference native icons?

I'm using Cordova 3.5 to build an app which contains a menu with pretty standard items in the list (home, contacts, etc.), and I want to use the native menu icons whenever possible. I believe those icons are already on the device as part of the OS, but I don't know if Cordova gives me a way to reference them.
I suppose I'd need to write a Javascript function to choose the right file name based on the platform, e.g.:
// this is pseudocode
var icon = '';
if (platform === 'android') {
icon = 'some/path/home.png';
} else {
icon = 'other/path/icon.home.png';
// or maybe a function such as the following exists:
// icon = cordova.getNativeIcon('icon.home.png');
}
$('.selector').css('background-image', icon);
Alternatively, I may be able to make do by referencing the files in CSS, e.g.:
.android .home-icon {
background-image: url('some/path/home.png');
}
.ios .home-icon {
background-image: url('other/path/icon.home.png');
}
So, how do folks handle this sort of thing in Cordova? Is there a function I can use to access native icons? Are folks just copying them into their projects? What's the best practice?
If you're working with Cordova, then you'll be working inside a web view provided by the host OS and you won't have direct access to any artwork. I've found that using icon fonts and CSS "themes" to work well enough, but that approach will replicate artwork already provided. There's extra work involved with theming for iOS 6 vs iOS 7 or 8, for example, but it's not as bad as it sounds.
IBM does have an article on partitioning your view between native and web controls, but it sounds a bit cumbersome. More details here: https://www.ibm.com/developerworks/community/blogs/worklight/entry/ios_combining_native_and_web_controls_in_cordova_based_applications

How to import a SpriteFont into MonoGame

I'm porting a simple tetris-like XNA app to Android, using Mono For Android and MonoGame; I have followed the suggested steps in this link and so far, everything compiles well, and no relevant warnings fire up. However, upon loading the contents, a null parameter exception breaks the program at the point below in my program:
protected override void LoadContent() {
// ...
_font = Content.Load<Microsoft.Xna.Framework.Graphics.SpriteFont>("SpriteFont1");
// ...
}
The content root directory is set in the game constructor class:
public Game2 (){
Content.RootDirectory = "Content";
Content.RootDirectory = "Assets/Content"; // TEST.
//...}
And I have tried several combinations, all to no avail.
I have also tried setting the xnb files as Content as well as Android Assets in the Build Action property; having the linked, copied always, copied only if newer... etc.
Either way, my problem is that I don't really understand WHY and HOW should I do this. I'm rather new to the platform and to XNA as well, so this may very well be a newbie question, but the truth is after several hours banging my head and fists against the monitor/keyboard I feel stuck and need your help.
I have a library that supports variable-width fonts (generated by BMFont) on MonoGame. Unfortunately it is a renderer and so has other code around it. However, the basic idea is very simple. You can take a look at the loader here and the mesh builder (given a string) here. This builder supports fonts that spread characters across multiple pages, too.
Hope this helps!
MonoGame (2.5.1) throws NotImplementedException in ContentManager.Load for SpriteFont type. Have the same not resolved problem. I'm trying not to use DrawString.
For loading textures in Win32 application I use:
Content.RootDirectory = #"../../Content";
var sampleTexture = Content.Load<Texture2D>("Sample.png");
You even must not add it to solution.
For Andoind (MonoDroid) application you must add "Content" folder to your solution and set "Andtoid Asset" in "Sample.png" properties.
Content.RootDirectory = "Content";
var sampleTexture = Content.Load<Texture2D>("Sample.png");
See also:
http://monogame.codeplex.com/discussions/360468
http://monogame.codeplex.com/discussions/267900

Categories

Resources