Issue building UWP app using MSBuild (GENERATEPROJECTPRIFILE) - msbuild

I am trying to build a UWP app from the command-line in an effort to automate the builds from check-in to publishing to the store. Everything works fine when running the builds from within Visual Studio and when I create app packages, it all works fine (but takes too long, 15 minutes or so).
While invoking msbuild per platform (x86, x64 & ARM), only ARM seems to fail with the following error:
_CreatePriConfigXmlForSplitting
"C:\Source\MyProject\src\MyProject\MyProject.csproj" (Build target) (1) ->
(_SplitResourcesPri target) ->
error PRI175 : 0x80070002 - Processing Resources failed with error : The system cannot find the file specified. [C:\Source\MyProject\src\MyProject\MyProject.csproj]
GENERATEPROJECTPRIFILE : error PRI252: 0xdef00071 - File C:\Source\MyProject\output\Release\x86\arm\MyProject\resources.pri not found. [C:\Source\MyProject\src\MyProject\MyProject.csproj]
0 Warning(s)
2 Error(s)
As you probably noticed, it's using x86\arm directory instead of arm, hence the build is failing.
I am using Cake to build this, below is (relevant part of) the script:
Task("Build")
.IsDependentOn("Clean")
.IsDependentOn("UpdateVersion")
.IsDependentOn("RestorePackages")
.Does(() =>
{
var platforms = new Dictionary<string, PlatformTarget>();
platforms["ARM"] = PlatformTarget.ARM;
platforms["x86"] = PlatformTarget.x86;
platforms["x64"] = PlatformTarget.x64;
foreach (var platform in platforms)
{
Information("Building project for platform {0}", platform.Key);
var outputDirectory = "../../" + outputRootDirectory + "/" + platform.Value.ToString();
var projectFileName = string.Format("./src/{0}/{0}.csproj", solutionName);
var msBuildSettings = new MSBuildSettings {
Verbosity = Verbosity.Diagnostic, // Verbosity.Minimal
ToolVersion = MSBuildToolVersion.VS2017,
Configuration = configurationName,
MSBuildPlatform = MSBuildPlatform.x86, // Always require x86, see platform for actual target platform
PlatformTarget = platform.Value
};
// Need special path since this is relative to the project file, not the cake build directory
//msBuildSettings.Properties["OutputPath"] = new List<string>(new [] { outputDirectory });
// We don't create native builds, we will use MSIL builds which the store will recompile,
// for more info see https://oren.codes/2015/12/03/continuous-integration-for-uwp-projects-making-builds-faster/
msBuildSettings.Properties["UseDotNetNativeToolchain"] = new List<string>(new [] { "false" });
msBuildSettings.Properties["BuildAppxUploadPackageForUap"] = new List<string>(new [] { "true" });
//msBuildSettings.Properties["AppxPackageArtifactsDir"] = new List<string>(new [] { outputDirectory });
// Fix for broken targets
//msBuildSettings.Properties["ProjectPriFileName"] = new List<string>(new [] { "resources.pri" });
//msBuildSettings.Properties["ProjectPriFullPath"] = new List<string>(new [] { outputDirectory + "/resources.pri" });
//msBuildSettings.Properties["_TransformedProjectPriFullPath"] = new List<string>(new [] { outputDirectory + "/resources.pri" });
MSBuild(projectFileName, msBuildSettings);
}
});
A. As you can see I am experimenting a bit by manually overriding the ms build properties, but no luck so far.
B. At first I thought it was GenerateProjectPriFile task that was failing. However, after some investigation I found out that creating the split files already show use the wrong startIndexAt value:
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<packaging>
<autoResourcePackage qualifier="Language" />
<autoResourcePackage qualifier="Scale" />
<autoResourcePackage qualifier="DXFeatureLevel" />
<omitSchemaFromResourcePacks />
</packaging>
<index root="\" startIndexAt="C:\Source\MyProject\output\Release\x86\arm\MyProject\resources.pri">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
</index>
</resources>
I have no idea why it prepends x86 before ARM when building for ARM. Any help is appreciated. In the meantime I'll continue investigating and update this post if I find something new.

It looks like I have to specify the sln file, not the csproj file. This is a bit unfortunate since now it builds much more than it needs to (there are multiple projects in the same solution), but I can get around that by creating a custom MyProject.Build.sln file

Related

Adapter is not working as expected in my test device

i have started to develop and implement adapter successfully in ibm web console and also android mobile browser simulator. But when installed in my real test device the adapter is not able to connect to the database. i do no where to find error log in mobile.
currentPage={};
currentPage.init = function() {
WL.Logger.debug("Page2 :: init");
};
currentPage.back = function(){
WL.Logger.debug("Page2 :: back");
$("#pagePort").load(pagesHistory.pop());
};
function loadSQLRecords(){
var invocationData = {
adapter : 'dball',
procedure : 'getDball',
parameters : []
};
WL.Client.invokeProcedure(invocationData,{
onSuccess : loadSQLQuerySuccess,
onFailure : loadSQLQueryFailure
});
}
function loadSQLQuerySuccess(result){
alert ("success");
if (result.invocationResult.resultSet.length > 0)
displayFeeds(result.invocationResult.resultSet);
else
alert("failure here");
}
function loadSQLQueryFailure() {
alert ("failure");
}
function displayFeeds(result){
for (var i = 0; i < result.length; i++) {
$("#mytable").append("<tr><td>" + result[i].EMPID + "</td></tr>");
$("#mytable").append("<tr><td>" + result[i].EMPNAME + "</td></tr>");
$("#mytable").append("<tr><td>" + result[i].EMAILID + "</td></tr>");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
- <!-- Licensed Materials - Property of IBM
5725-I43 (C) Copyright IBM Corp. 2011, 2013. All Rights Reserved.
US Government Users Restricted Rights - Use, duplication or
disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
-->
- <wl:adapter name="dball" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wl="http://www.ibm.com/mfp/integration" xmlns:sql="http://www.ibm.com/mfp/integration/sql">
<displayName>dball</displayName>
<description>dball</description>
- <connectivity>
- <connectionPolicy xsi:type="sql:SQLConnectionPolicy">
- <!-- Example for using a JNDI data source, replace with actual data source name
-->
- <!-- <dataSourceJNDIName>java:/data-source-jndi-name</dataSourceJNDIName>
-->
- <!-- Example for using MySQL connector, do not forget to put the MySQL connector library in the project's lib folder
-->
- <dataSourceDefinition>
<driverClass>oracle.jdbc.driver.OracleDriver</driverClass>
<url>jdbc:oracle:thin:#192.168.*.***:****:****</url>
<user>****</user>
<password>****</password>
</dataSourceDefinition>
</connectionPolicy>
</connectivity>
- <!-- Replace this with appropriate procedures
-->
<procedure name="getDball" />
<procedure name="addDball" />
</wl:adapter>
I took your project and changed the database settings to connect to mine instead (MySQL). The connection was successful and data was saved in the database.
Even if forcing it to fail, it does not fail with "Error is UNDEFINED", so I still believe this does have to do with your Oracle database settings. 192.168 is internal IP address - it is not available as a public IP address even if you think it is. It does not. You need to check this with your IT department and get the real IP address of your database.

Unable to Edit/Create playlists in "playlists" container in Sonos version 5.4 (latest update)

When I updated to version 5.4 I no longer have the option to create a playlist in the "playlists" container, nor to add a track to a playlist already existing in it. In version 5.3 it was working well. I also checked other Music Services on Sonos, same problem. Did anything change in the specifications for User Content Playlists that is not specified in the documentation for Playlist Editing?
This is how I'm adding my User Content container:
$result->mediaCollection[] = array('id'=>'playlists', 'title'=>'My Playlists', 'itemType'=>'favorites', 'containsFavorite'=>true, 'displayType'=>'genreList', 'readOnly'=>false, 'userContent'=>true, 'renameable'=>true, 'albumArtURI'=>PATH.'/img.png');
Edit:
I am using the Android controller (version 5.4, build 29590261) and I am testing on a Play:1 (version 5.4, build 29591030).
I am able to add a song/playlist to an already existing playlist or to a new playlist (by long press on a song to get to the extended metadata, and then "Add Track to 'Service Name' Playlist"), but what I can't figure out how to do is: deleting a playlist, renaming a playlist, and editing songs in a playlist (reorder, delete songs). I don't have a screenshot for version 5.3 but there was an button in the top right corner (three vertical dots) of the playlists container from which one can edit playlists or create new ones (check the screenshots below, from version 5.4). Am I missing something?
Edit 2:
I figured out what is causing the issue. I am using the .wsdl for beta in order to be able to implement Custom Item Display (This is not beta anymore, as I understood from the Adding New SMAPI Features page). When I revert to the normal Sonos.wsdl file from the Sonos Documentation, the info and options button appears again. How can I use Custom Item Display while keeping the info and options button there and all functionalities of playlist editing unchanged?
Note: the Sonos(beta).wsdl was here but it's not available anymore.
Edit 3:
I downloaded the Sonos.wsdl from the Sonos documentation, but I still can't see the button. In order to reproduce the issue, please check the following PHP implementation and Presentation Map XML code:
PHP implementation:
define('BASE_PATH', rtrim("http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']), '/'));
class SonosAPI
{
public function getMetadata($args)
{
$result = new StdClass();
$result->index = $args->index;
switch($args->id) {
case 'root':
$result->mediaCollection[] = array('id'=>'playlists', 'title'=>'My Playlists', 'itemType'=>'favorites', 'displayType'=>'genreList', 'readOnly'=>false, 'userContent'=>true, 'renameable'=>true, 'albumArtURI'=>BASE_PATH.'/image.png');
$result->count = $result->total = 1;
break;
case 'playlists':
$result->mediaCollection[] = array('id'=>'123', 'title'=>'Title', 'itemType'=>'playlist', 'displayType'=>'genreList', 'canPlay'=>true, 'readOnly'=>false, 'userContent'=>false, 'renameable'=>true, 'albumArtURI'=>BASE_PATH.'/image.png');
$result->count = $result->total = 1;
break;
}
return array('getMetadataResult' => $result);
}
}
$server = new SoapServer("Sonos.wsdl", array('cache_wsdl' => 0)); // disable cache in development
$server->setClass('SonosAPI');
try {
$server->handle();
} catch (Exception $e) {
Log("[ERROR] ".$e->getMessage());
}
?>
Presentation Map file:
<?xml version="1.0" encoding="utf-8" ?>
<Presentation>
<PresentationMap type="DisplayType">
<DisplayType id="genreGrid">
<DisplayMode>GRID</DisplayMode>
</DisplayType>
<DisplayType id="genreList">
<DisplayMode>LIST</DisplayMode>
</DisplayType>
<DisplayType id="genreHero">
<DisplayMode>HERO</DisplayMode>
</DisplayType>
<DisplayType id="genreEditorial">
<DisplayMode>EDITORIAL</DisplayMode>
</DisplayType>
<DisplayType id="twoLine">
<Lines>
<Line token="title"/>
<Line token="summary"/>
</Lines>
</DisplayType>
</PresentationMap>
</Presentation>
XML response to getMetadata of root (which contains the playlists container):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns1="http://www.sonos.com/Services/1.1" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns1:getMetadataResponse>
<ns1:getMetadataResult>
<ns1:index>0</ns1:index>
<ns1:count>4</ns1:count>
<ns1:total>4</ns1:total>
<ns1:mediaCollection>
<ns1:id>rootlang:ar</ns1:id>
<ns1:itemType>collection</ns1:itemType>
<ns1:displayType>genreGrid</ns1:displayType>
<ns1:title>Arabic</ns1:title>
<ns1:albumArtURI>{SOME LINK}</ns1:albumArtURI>
</ns1:mediaCollection>
<ns1:mediaCollection>
<ns1:id>rootlang:en</ns1:id>
<ns1:itemType>collection</ns1:itemType>
<ns1:displayType>genreGrid</ns1:displayType>
<ns1:title>International</ns1:title>
<ns1:albumArtURI>{SOME LINK}</ns1:albumArtURI>
</ns1:mediaCollection>
<ns1:mediaCollection>
<ns1:id>rootlang:default</ns1:id>
<ns1:itemType>collection</ns1:itemType>
<ns1:displayType>genreGrid</ns1:displayType>
<ns1:title>Arabic + International</ns1:title>
<ns1:albumArtURI>{SOME LINK}</ns1:albumArtURI>
</ns1:mediaCollection>
<ns1:mediaCollection renameable="true" readOnly="false" userContent="true">
<ns1:id>playlists</ns1:id>
<ns1:itemType>favorites</ns1:itemType>
<ns1:displayType>genreList</ns1:displayType>
<ns1:title>My Playlists</ns1:title>
<ns1:albumArtURI>{SOME LINK}</ns1:albumArtURI>
</ns1:mediaCollection>
</ns1:getMetadataResult>
</ns1:getMetadataResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML response to getMetadata of playlists:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns1="http://www.sonos.com/Services/1.1" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns1:getMetadataResponse>
<ns1:getMetadataResult>
<ns1:index>0</ns1:index>
<ns1:count>1</ns1:count>
<ns1:total>1</ns1:total>
<ns1:mediaCollection renameable="true" readOnly="false" userContent="false">
<ns1:id>playlist:19663408</ns1:id>
<ns1:itemType>playlist</ns1:itemType>
<ns1:displayType>genreList</ns1:displayType>
<ns1:title>Test Playlist</ns1:title>
<ns1:canPlay>true</ns1:canPlay>
<ns1:albumArtURI>{SOME LINK}</ns1:albumArtURI>
</ns1:mediaCollection>
</ns1:getMetadataResult>
</ns1:getMetadataResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Custom Display Types were made available in the most recent production software update. The beta wsdl that you were using is for v5.4 which is now the current production build. Make sure that you are using the production version of the wsdl and you will have info & options and also have access to Custom Display Types (provided they are properly enabled in your service).
However I have confirmed that we do have a bug when using Display Types with playlist containers when playlist editing is enabled. The work around is to removed the displayType node from your root playlist and child playlist containers (all other containers that use displayType do not need to be changed). This work around has been tested and works. We have opened an issue to track this internally.

Titanium - App does show from notification only once

My app sometimes displays multiple android notifications. When someone clicks on them, my app should show up with the content of the notifications.
I've managed to do it, but it only works for the first notification the user clicks on. If I leave the application after this (for example with the homebutton) and click then on the next notification, nothing happens.
I've created an example application to show you what I have at the moment. You can find it here: https://github.com/VanCoding/TitaniumNotificationTest
What am I doing wrong? How do I achieve what I want?
app.js
if(!Ti.App.Properties.getBool("displayedNotifications")){
var notifications = ["Apple","Orange","Banana"];
for(var i = 0; i < notifications.length; i++){
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
packageName:"com.company.notificationtest",
className:"com.company.notificationtest.NotificationtestActivity",
flags:Ti.Android.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
});
intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
intent.putExtra("name",notifications[i]);
Titanium.Android.NotificationManager.notify(i, Titanium.Android.createNotification({
contentTitle: notifications[i],
contentText : notifications[i],
contentIntent: Ti.Android.createPendingIntent({
intent:intent,
type : Ti.Android.PENDING_INTENT_FOR_ACTIVITY,
flags : Ti.Android.FLAG_ACTIVITY_NO_HISTORY
}),
flags : Titanium.Android.ACTION_DEFAULT | Titanium.Android.FLAG_AUTO_CANCEL | Titanium.Android.FLAG_SHOW_LIGHTS
}));
}
Ti.App.Properties.setBool("displayedNotifications",true);
}
tiapp.xml
<?xml version="1.0" encoding="UTF-8"?>
<ti:app xmlns:ti="http://ti.appcelerator.org">
<id>com.company.notificationtest</id>
<name>NotificationTest</name>
<version>1.0</version>
<publisher>not specified</publisher>
<url></url>
<description>not specified</description>
<copyright>not specified</copyright>
<icon>appicon.png</icon>
<fullscreen>false</fullscreen>
<navbar-hidden>false</navbar-hidden>
<analytics>true</analytics>
<guid>91e86075-373b-44e0-9416-66183390e8af</guid>
<property name="ti.ui.defaultunit" type="string">dp</property>
<android xmlns:android="http://schemas.android.com/apk/res/android">
</android>
<modules>
</modules>
<deployment-targets>
<target device="android">true</target>
</deployment-targets>
<sdk-version>3.2.3.GA</sdk-version>
</ti:app>
Changing:
contentIntent: Ti.Android.createPendingIntent({
intent:intent,
type : Ti.Android.PENDING_INTENT_FOR_ACTIVITY,
flags : Ti.Android.FLAG_ACTIVITY_NO_HISTORY
}),
to:
contentIntent: Ti.Android.createPendingIntent({
intent:intent,
type : Ti.Android.PENDING_INTENT_FOR_ACTIVITY
}),
fixes it for me. Tested using 3.3.0.GA.

Unable to load SWF from application storage directory

While publishing my AIR application(CurrentFile), I have also included chatFile.swf with the installation files.
In my AIR settings panel [AIR 3.7 for Desktop], under 'Include Files' I have the following:
CurrentFile.swf
CurrentFile-app.xml
chatFile.swf
Here is the AS3 code in my CurrentFile.swf:
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.Loader;
import flash.filesystem.File;
var chatLoaderWindow:Loader;
function loadchat(m:MouseEvent):void
{
chatLoaderWindow = new Loader();
chatLoaderWindow.contentLoaderInfo.addEventListener(Event.COMPLETE, chatLoadComplete);
chatLoaderWindow.contentLoaderInfo.addEventListener(Event.INIT, chatInitLoad);
chatLoaderWindow.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, chatErrorLoad);
chatLoaderWindow.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, chatHttpStatus);
myclip.chatwindow.addChild(chatLoaderWindow);
var f:File = File.applicationStorageDirectory.resolvePath("chatFile.swf");
chatLoaderWindow.load(new URLRequest(f.url));
tracebox.text = "Chat URL" + f.url;
}
function chatLoadComplete(e:Event):void
{
tracebox.text = "chat loaded";
}
function chatErrorLoad(io:IOErrorEvent):void
{
tracebox.text = "chat IO Error: "+io;
}
function chatInitLoad(i:Event):void
{
tracebox.text = "chat INIT";
}
function chatHttpStatus(e:HTTPStatusEvent):void
{
tracebox.text = "chat Http"+e;
}
myclip.chatbut.addEventListener(MouseEvent.CLICK,loadchat);
/*
Output:
chat IO Error: [IOErrorEvent type="ioError" bubbles=false cancelable=false eventPhase=2 text="Error #2035" errorID=2035]
EDIT: I figured it out. It was really simple
This is not required:
var f:File = File.applicationStorageDirectory.resolvePath("chatFile.swf");
chatLoaderWindow.load(new URLRequest(f.url));
Insert this:
chatLoaderWindow.load(new URLRequest("app:/chatFile.swf"));
So now my question is:
What is the purpose of File.applicationStorageDirectory.resolvePath?
There are two directories here. One is the "application" directory, where your install files are placed. One is the "application-storage" directory, which is a convenient place to write files to at runtime. To access these directories you can either use the File.resolvePath() function or use the URI-scheme shortcuts, app: or app-storage:. In your initial attempt, you were just looking in the wrong directory for your file.
File.applicationStorageDirectory.resolvePath("somefile.swf").url will equal "app-storage:/somefile.swf"
File.applicationDirectory.resolvePath("somefile.swf").url will equal "app:/somefile.swf"
The application directory is where your app was installed. The app storage directory is a folder your app can save files to.
resolvePath() returns a file object. You can use it for purposes other than getting the cross-platform url for the file location, such as fileObj.exists and fileObj.parent.createDirectory(). fileObj.url is just the url you would use with URLLoader to access the file in a platform-independent manner.

How can I specify a different config file for testing in Play 2.1

I would like to define different database connections for multiple test environments(Production, Staging, Development). After reading the post "How do I specify a config file with sbt 0.12.2 for sbt test?" it seems that it was possible in earlier versions of Play, by using the follwing SBT setting:
val main = play.Project(appName, appVersion, appDependencies).settings(
javaOptions in Test += "-Dconfig.file=conf/test.conf"
)
But if I use this setting in my Build.scala, I get the following error:
not found: value javaOptions
So my question is, how can I define different connections for different test environments?
Edit:
A possible workaround would be to override the default setting during testing. This can be done with a environment variable.
object Config {
var defaultConfig = Map(
"db.default.user" -> "user",
"db.default.pass" -> "************"
)
def additionalConfiguration(): Map[String, _] = sys.env.getOrElse("PLAY_TEST_SCOPE", "") match {
case "development" => {
defaultConfig += "db.default.url" -> "jdbc:mysql://host:3306/development"
defaultConfig
}
case "staging" => {
defaultConfig += "db.default.url" -> "jdbc:mysql://host:3306/staging"
defaultConfig
}
case "production" => {
defaultConfig += "db.default.url" -> "jdbc:mysql://host:3306/production"
defaultConfig
}
case _ => {
throw new Exception("Environment variable `PLAY_TEST_SCOPE` isn't defined")
}
}
}
And then running a fake application with this configuration.
FakeApplication(additionalConfiguration = Config.additionalConfiguration())
javaOptions is contained within the Keys object.
Make sure that you use the proper import in your Build.scala file:
import Keys._
we can mix the above solutions, to pass the config file as a parameter to sbt.
This will be useful to integrate the test in CI pipeline
First, in the Build.scala file
val testOptions = "-Dconfig.file=conf/" + Option(System.getProperty("test.config")).getOrElse("application") + ".conf"
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
javaOptions in Test += testOptions
)
Then, in the command line to run the test with integ.conf
sbt -Dtest.config=integ test
to use the default application.conf
sbt test
Update for Play 2.5.x
Explicit import for import Keys._ is no longer required, and the vm param for config resource location has changed.
javaOptions in Test += "-Dconfig.resource=<conf_name>.conf"
You can run your application from console with alternative config file, anyway you need to use -Dconfig.file with full path as there are some problems ... that I can't realize with other option. For an example in unix env:
play -Dconfig.file=/home/akkie/play/some-project/conf/local_akkie_dev.conf "~run 9123"
Of course for easier launching you can create bash script for calling this line.
Edit: Note that you don't need to write whole config in each additional config file, as you can just include your main config at beginning and then overwrite only required properties :
include "application.conf"
key.to.override=blah
Take a look to the official doc