Two Phonegap apps with same code base? - android

I'm developing Phonegap application (using AngularJs+Bootstrap) which supports iOS and Android. We had to maintain two code bases so far but its the same functionalities, only few differences like below.
Application name/icons are different
Main url is different for web-service calls
Ex :
PhoneGap App X : call http://abc/xappinfo weservice, use x_icon_app.png
(This has to build for both iOS and Android which i have no issue)
PhoneGap App Y : call http://xyz/yappinfo weservice, use y_icon_app.png and other UI elements for mobile skin
(This also has to build for both iOS and Android)
Both PhoneGap App X and Y uses same code for business logics.
I would like to maintain one code base for both apps since there only few differences. Is there any way I could achieve this or simplify my development effort?

I had a similar situation. I placed all my app folders in a single folder and placed the following code in a file in the root folder called: persist.js. Its purpose is to persist file changes across all of the different apps keeping the same path. It is a little manual, but works...
var fs = require('fs');
var chalk = require('chalk');
var argv = require('minimist')(process.argv.slice(2));
var file = argv.f;
var apps = [
'app_folder_1',
'app_folder_2',
'app_folder_3',
'app_folder_4',
'app_folder_5',
];
if(file){
if (fs.existsSync(file)) {
console.log(chalk.blue('Found source file'));
var fileWithoutApp = file.substring(file.indexOf('/'));
apps.map(app => {
fs.writeFileSync(app + fileWithoutApp, fs.readFileSync(file));
console.log(chalk.green(`File copied to: ${app + fileWithoutApp}`))
});
} else {
console.log(chalk.red('File does not exist'));
}
} else {
console.log(chalk.red('No file specified'));
}
After changes are made to a file within any of the project folders just call the following from the command line:
node persist -f [relative path to your file that has changes]
This will persist the change across all projects. Like I said, a little manual... but effective :)

When u use cordova or ionic + angularjs you can compile application for both device this is more simple you like complication !!

Related

Protractor locators does not work in PageObjectModel structure

Framework: Appium + Protractor + Cucumber + Typescript using POM model
I have the protractor framework for appium designed in POM structure
The initial page of the app will identify the locators calling in a different ts file and the functions such as tap, isDisplayed calling it in a different ts file.
But once it passes the initial pages in the app,say 3 pages. the locators are not identified which are calling other function, but they are identified when they are passed directly ( like driver.findelements(by.css('')).click ) this works.
The problem is I can't pass this code like this within the step definition .ts file always as it is not a good structure
Note: By the way, this script was working fine earlier.
tried to test using a different workaround, like building the binary again, trying to run on android and ios application, downgrading or upgrading the node packages. But nothing solved the problem. has anyone faced this kind of issue. Any suggestions or solutions for this problem, please?
Code which works: (Passing the locators directly in the function, rather than from the onboarding.ts file will work)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await browser.driver.findElement(by.css('button[sp-automation-id=\'select-state-toggle\']')).click();
await browser.driver.findElement(by.css('page-action-sheet label[sp-automation-id=\'action-sheet-option-VIC\']')).click(); });
Code which does not work: (Onboarding.ts file contains the locators defined for State and VIC same as the above code block. But reading from there it does not work.)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await AutomationAction.tap(Onboarding.State);
await AutomationAction.tap(Onboarding.VIC); });
Code which works (The below code is called before the above code block, it's a page before calling the above pages)
Then(/^I enter the mobile number and tap next button on the your mobile number screen$/, async () => {
MobileNo = AutomationAction.getMobileNumber("mobileNumber");
SameMobileNo = MobileNo;
await AutomationAction.sendKeyText(Onboarding.InputMobileNo,MobileNo);
await AutomationAction.tap(Onboarding.Next_BTN_YourMobileNumber);
});
Because of the page where it is failing the automation thinks its as non-angular page and the locators used to fail or not locate them when calling it in a different function. When I introduced browser.ignoreSycnhronization=true to make Angular sync for non-angular apps/pages it worked.

How can i embed an NativeScript Angular app in iOS / Android and navigate to certain routes from the existing app

We are looking to integrate NativeScript Angular into existing iOS and Android apps. We would like to have existing menus in our app be able to route to sections of the NS Angular app. /home /contact for example. One of our concerns with embedding an NS Angular app is the large overhead for frameworks / vendor files / etc and having to duplicate these sections over and over for multiple embedded apps. We would rather have one NS Angular app that contains various views and be able to navigate to those views as the starting view based on the initial link tapped in the previous Native app that hosts the embed.
Has anyone achieved this already and can share some examples or any info that would help? Would sending a variable from the native app to the embedded NS Angular app that routes be on option?
in https://github.com/NativeScript/sample-ios-embedded/blob/master/HOWTO.md
there is mention of _runScript
- (void)activateNativeScript:(id)sender {
NSString *source = #"var application = require('application');"
"application.start({ moduleName: 'main-page' });";
[self _runScript: source];
}
Would we be able to send routes through _runScript or possibly initialize various sections but still maintain the same vendor bundle.js ?
thanks!
I don't think you could access Angular from outside Angular context. A workaround could be, store the RouterExtensions reference on global variable while your appcomponent.ts is initiated,
export class AppComponent {
constructor(private routerExtensions: RouterExtensions) {
(<any>global)._routerExtensions = routerExtensions;
}
}
You may do this with _runScript then
NSString *source = #"global._routerExtensions.navigate([...])";
But make sure you access _routerExtensions once it's initialised. Also the code to start Angular app is slightly different, you will find it in the same docs if you go down a little further.
- (void)activateNativeScript:(id)sender {
NSString *source = #"var platform = require('nativescript-angular/platform');"
"var AppModule = require('./app.module' });"
"platform.platformNativeScriptDynamic().bootstrapModule(AppModule);";
[self _runScript: source];
}

Titanium Hyperloop access to android.os.SystemProperties

I have been trying a ( i hope) simple bit of Android hyperloop code directly within a titanium project (using SDK 7.0.1.GA and hyperloop 3).
var sysProp = require('android.os.SystemProperties');
var serialNumber = sysProp.get("sys.serialnumber", "none");
But when the app is run it reports
Requested module not found:android.os.SystemProperties
I think this maybe due to the fact that when compiling the app (using the cli) it reports
hyperloop:generateSources: Skipping Hyperloop wrapper generation, no usage found ...
I have similar code in a jar and if I use this then it does work, so I am wondering why the hyperloop generation is not being triggered, as I assume that is the issue.
Sorry should have explained better.
This is the jar source that I use, the extraction of the serial number was just an example (I need access to other info manufacturer specific data as well), I wanted to see if I could replicate the JAR functionality using just hyperloop rather that including the JAR file. Guess if it's not broke don't fix it, but was curious to see if it could be done.
So with the feedback from #miga and a bit of trial and error, I have come up with a solution that works really well and will do the method reflection that is required. My new Hyperloop function is
function getData(data){
var result = false;
var Class = require("java.lang.Class");
var String = require("java.lang.String");
var c = Class.forName("android.os.SystemProperties");
var get = c.getMethod("get", String.class, String.class);
result = get.invoke(c, data, "Error");
return result;
}
Where data is a string of the system property I want.
I am using it to extract and match a serial number from a Samsung device that is a System Property call "ril.serialnumber" or "sys.serialnumber". Now I can use the above function to do what I was using the JAR file for. Just thought I'd share in case anyone else needed something similar.
It is because android.os.SystemProperties is not class you can import. Check the android documentation at https://developer.android.com/reference/android/os/package-summary.html
You could use
var build = require('android.os.Build');
console.log(build.SERIAL);
to access the serial number.

Xamarin.Forms Android File Exchange, MTP

I am trying to exchange files between a .Net Desktop App and a Xamarin.Forms Android app. I really had trouble getting resources and help, so I want this question to also wrap some stuff up - for other interested users (not only of Xamarin Forms)
So far I got to read files and folders in .Net C# using
Christophe Geers' Blog and Fun with MTP and because writing did not work on all of my devices Windows File Stuff by Flauschig
On Xamarin.Forms side of the wall I first stumbled over Xamarin doc and A lib to store from pcl code and also Plugin.Permissions.
With all these sources above I was able to get reading and writing on the Android (Samsung A5, Android 6.0) to work.
With this description on filestructure I thought the following Code will always get a valid path:
public string GetExternalFolder()
{
GetPermission();
var externalFolder = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, "Android", "data", "com.exampledom.appname", "files");
if (!Directory.Exists(externalFolder))
CreateFolderStructure();
return externalFolder;
}
GetPermission() is taken from Plugin.Permissions and will throw exception if permission is not given.
CreateFolderStructure() is using pcl.storage - and looks like this.
private async void CreateFolderStructure()
{
try
{
IFolder rootFolder = await FileSystem.Current.GetFolderFromPathAsync(Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path));
var subpaths = new[] {"Android", "data", "com.exampledom.appname", "files"};
foreach (var dir in subpaths)
{
if (!string.IsNullOrEmpty(dir))
rootFolder = await rootFolder.CreateFolderAsync(dir, CreationCollisionOption.OpenIfExists);
}
Log("Folder structure created!");
}
catch (Exception e)
{
Log("Folder structure cannot be created!");
Console.WriteLine("Failed to log! " + e.Message);
}
}
Ok, now for the question:
The Folder that is created by this Method is only created on one device I tested on (proof of concept) - all others (eg Samsung A3, Android 6.0) nothing happens(proof of helpless developer). A reboot is not the solution.
Also on the device this works on - the permission is requested as expected. There is no permission request on the other devices.
Why is the desired folder not created during install? It seems all other apps do have such a folder 'Android/data/com.exampledom.appname/files'.
What am I missing? It seems overly hard to import/export to android.
#smack Does CreationCollisionOptions.OpenIfExists really create a folder? I don't think so. Is there not CreateIfNotExists enum?

How to invoke an app from another app in flex mobile

Is there a way to open one app from another app in Air? Example: I open app A which contains a button that opens app B when clicked. Suppose both A and B are separated apps that are installed in the device and that this device could be a PlayBook, an Ipad or an Android tablet.
Thanks.
You'd have to go the Air Native Extension(ANE) route. Either create one ANE solution for iOS and Android each, or one ANE that abtracts the functionality into one solution. How to launch app A from app B on Android is not the same as on iOS. See this answer in SO.
To implement it on Android, you'd wraps the native Android Java solution in a ANE. The native Java code uses the package name of app B to launch app B from app A:
Intent intent = getPackageManager().getLaunchIntentForPackage("com.yourdoman.yourapp");
startActivity(intent);
Here is a video tutorial on how to launch an Activity through an ANE which you can build on to create your ANE. You'd have to tailor the solution to launch by domain instead of Activity.
Since I really don't know the specifics of what you are trying to do, I think I should point you here: http://www.riaspace.com/2011/08/defining-custom-url-schemes-for-your-air-mobile-applications/ It is the best answer to the question that I am aware of.
private function getHostName() : void
{
if (NativeProcess.isSupported)
{
var OS : String = Capabilities.os.toLocaleLowerCase();
var file : File;
if (OS.indexOf('win') > -1)
{
// Executable in windows
file = new File('C:\\Windows\\System32\\hostname.exe');
}
else if (OS.indexOf('mac') > -1 )
{
// Executable in mac
}
else if (OS.indexOf('linux'))
{
// Executable in linux
}
var nativeProcessStartupInfo : NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process : NativeProcess = new NativeProcess();
process.addEventListener(NativeProcessExitEvent.EXIT, onExitError);
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutput);
process.start(nativeProcessStartupInfo);
process.closeInput();
}
}
private function onOutput(event : ProgressEvent) : void
{
var strHelper : StringHelper = new StringHelper();
formStationID.text = event.target.standardOutput.readUTFBytes(event.target.standardOutput.bytesAvailable);
formStationID.text = strHelper.trimBack(formStationID.text, "\n");
formStationID.text = strHelper.trimBack(formStationID.text, "\r");
}
This code gets the workstation name. I have heard this can be done on IOS and Android, but I haven't found any proof of that yet.

Categories

Resources