Aprovechando que van a unificar y rebajar el precio de las licencias de Windows Store os cuento mi experiencia.
Por un lado creo que debería de ser gratis publicar apps, algo como lo que pasa en internet. Tu publicas y la gente decide si les gusta o no.
Por otro lado también entiendo que hace falta un control de calidad antes de permitir la entrada de apps en la store y eso cuesta dinero.
Hay otros que dicen que si fuera gratis todo el mundo subiría una porquería, ahí también difiero... Hay quien sube una porquería por no tirar el dinero... Yo sin ir más lejos.
Tuve una idea para dos apps hace un año, me saqué la licencia por 60€ pero me falló el diseñador y yo estoy siempre bastante liado así que no hice nada. Finalmente un mes antes de que me caducase me dije "¡Necesitas subir por lo menos una!" y así lo hice.
Hice el MorseCentral en un par de mañanas de sábado y la subí. Ya puedo decir que tengo una App en la store y que "no desperdicié" la licencia pero en realidad mi App de 6 horas de trabajo no ha servido para mejorar la store, más bien al contrario. Como toda App de 6h hecha por un novato tiene fallos técnicos y de usabilidad por no hablar del diseño que es una catástrofe.
En conclusión. Opino que si quieren que haya muchas apps que pongan gratis la licencia de desarrollo. Democracia al poder. Y siquieren que la store no se llene de mierda pues que hagan que las apps con menos de, digamos ¿100 descargas? y ninguna actualización en el último año se borren automáticamente.
Hey, al menos no he tirado 60€ por la alcantarilla. He entretenido a 60 desconocidos durante un par de segundos de su vida y entretenerlos solo me ha costado 1€ por persona :)
Mostrando entradas con la etiqueta Windows Phone. Mostrar todas las entradas
Mostrando entradas con la etiqueta Windows Phone. Mostrar todas las entradas
viernes, 8 de noviembre de 2013
domingo, 21 de abril de 2013
Batería y Tiles de Acceso Directo para WP8
Como posiblemente sabrás conseguí mi WP8 hace un par de semanas. Una de las cosas que me molesta es tener que ir a Configuración>LoQueSea>LoQueQuieres y lo suelo hacer un par de veces al día, todos los días. Eso quiere decir que me molesta 730 veces al año...
Genial! pensé. Voy a hacer una aplicación con tiles de accesos directos y por fin voy a tener una app en el marketplace que sea útil, una que tenga sentido.
Mientras me descargaba la SDK pensé que podría estar bien tener una aplicación que me dijese el nivel de la batería en una tile "Alguien debe haber hecho esto ya, iré al marketplace y pillaré alguna" Y tenía razón.
En el marketplace encontré Battery, una estupenda aplicación que muestra una gráfica con el nivel de la batería, tiene estadísticas sobre todo lo imaginable, te dice el nivel de carga y hasta te da una estimación del número de horas restantes hasta la próxima carga. ¡Excelente app! ¡este tío ha pensado en todo! pero... ¿Qué es eso?
La aplicación proporciona un juego de tiles de acceso directo y funcionan perfectamente. WiFi, Localización, Bluetooth, Modo vuelo y Red Movil.
miércoles, 5 de septiembre de 2012
Snippet para DependencyProperty con método Call-Back y valor por defecto
Para mi esta es la manera en la que Microsoft debería haber hecho el snippet de DependencyProperty desde el principio.
Uso este un montón y tiene definidos lugares para el valor por defecto, el método call-back e incluso asigna la instancia de la clase que llama al call-back a una variable automaticamente.
Por cierto, podéis encontrar más información sobre cómo crear e importar snippets aquí.
Uso este un montón y tiene definidos lugares para el valor por defecto, el método call-back e incluso asigna la instancia de la clase que llama al call-back a una variable automaticamente.
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Dependency Property With CallBack</Title>
<Shortcut>propdpCallBack</Shortcut>
<Description>Creates a dependency property with it's callback method</Description>
<Author>Jose Sanchez</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>PublicName</ID>
<Default>PropertyName</Default>
<ToolTip>Public name of the depencency property</ToolTip>
</Literal>
<Literal>
<ID>type</ID>
<Default>string</Default>
<ToolTip>Type of the property</ToolTip>
</Literal>
<Literal>
<ID>ParentClassType</ID>
<Default>UserControl</Default>
<ToolTip>Type of the parent class of the dependency property</ToolTip>
</Literal>
<Literal>
<ID>DefaultValue</ID>
<Default>string.Empty</Default>
<ToolTip>Default value of the dependency property</ToolTip>
</Literal>
<Literal>
<ID>CallBackName</ID>
<Default>PropertyCallBackName</Default>
<ToolTip>Name of the callback method that will be triggered when the depencency property has changed</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[public $type$ $PublicName$
{
get { return ($type$)GetValue($PublicName$Property); }
set { SetValue($PublicName$Property, value); }
}
// Using a DependencyProperty as the backing store for $PublicName$. This enables animation, styling, binding, etc...
public static readonly DependencyProperty $PublicName$Property =
DependencyProperty.Register("$PublicName$", typeof($type$), typeof($ParentClassType$), new PropertyMetadata($DefaultValue$, new PropertyChangedCallback($CallBackName$)));
private static void $CallBackName$(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
$ParentClassType$ Changed$ParentClassType$ = (obj as $ParentClassType$);
//TODO: Implement some actions in Changed$ParentClassType$
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Espero que os sea tan útil como a mi.Por cierto, podéis encontrar más información sobre cómo crear e importar snippets aquí.
jueves, 12 de enero de 2012
Sobre Windows Phone 7 y la autenticación con SharePoint
Conectar el teléfono a nuestro entorno de SharePoint era mi proyecto de navidad, y me llevó un rato... Al final conseguí hacerlo así que he pensado en compartir mi alegría. Además, he leído un montón de blogs sobre el tema ¿todos los que hay? y quería aportar mi granito de arena.
Vamos al asunto. Me he creado una clase llamada SPAuthBridge partiend del código de la SDK que puede ser usada para realizar las conexiones con el servidor de SharePoint.
La manera de usar esto es bastante simple, creas el objeto SPAuthBridge y, llamas al método Authenticate y listo, algo así:
Es preciosocuando funciona…
Vamos al asunto. Me he creado una clase llamada SPAuthBridge partiend del código de la SDK que puede ser usada para realizar las conexiones con el servidor de SharePoint.
using System;
using System.IO;
using System.Net;
using System.Text;
namespace PhoneUtils.Code
{
public class SPAuthBridge
{
#region Properties
public CookieContainer cookieJar = new CookieContainer();
string SiteUrl, User;
string Password; //This should be securestring, but I don't think it's available in WP7
#endregion
#region Constructors
public SPAuthBridge(string SiteUrl, string User, string Password)
{
this.SiteUrl = SiteUrl;
this.User = User;
this.Password = Password;
}
#endregion
#region Public Methods
public void Authenticate()
{
try
{
if (string.IsNullOrEmpty(SiteUrl)) throw new ArgumentOutOfRangeException("The SPAuthBridge was not properly initialized");
System.Uri authServiceUri = new Uri(string.Format("{0}/_vti_bin/authentication.asmx", SiteUrl));
HttpWebRequest spAuthReq = HttpWebRequest.Create(authServiceUri) as HttpWebRequest;
spAuthReq.CookieContainer = cookieJar;
spAuthReq.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/Login";
spAuthReq.ContentType = "text/xml; charset=utf-8";
spAuthReq.Method = "POST";
//add the soap message to the request
spAuthReq.BeginGetRequestStream(new AsyncCallback(spAuthReqCallBack), spAuthReq);
}
catch
{
TriggerOnAuthenticated(false);
}
}
#endregion
#region Private Methods
private void spAuthReqCallBack(IAsyncResult asyncResult)
{
string envelope =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<Login xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
<username>{0}</username>
<password>{1}</password>
</Login>
</soap:Body>
</soap:Envelope>";
UTF8Encoding encoding = new UTF8Encoding();
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
Stream _body = request.EndGetRequestStream(asyncResult);
envelope = string.Format(envelope, User, Password);
byte[] formBytes = encoding.GetBytes(envelope);
_body.Write(formBytes, 0, formBytes.Length);
_body.Close();
request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
}
private void ResponseCallback(IAsyncResult asyncResult)
{
try
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
Stream content = response.GetResponseStream();
if (request != null && response != null)
{
if (response.StatusCode == HttpStatusCode.OK)
{
using (StreamReader reader = new StreamReader(content))
{
//Put debugging code here
string _responseString = reader.ReadToEnd();
reader.Close();
}
}
}
//authentication complete
TriggerOnAuthenticated(true);
}
catch
{
TriggerOnAuthenticated(false);
}
}
#endregion
#region Events
public delegate void OnAuthenticatedHandler(bool Success);
public event OnAuthenticatedHandler OnAuthenticated;
protected virtual void TriggerOnAuthenticated(bool Success)
{
if (OnAuthenticated != null)
OnAuthenticated(Success);
}
#endregion
}
}
La manera de usar esto es bastante simple, creas el objeto SPAuthBridge y, llamas al método Authenticate y listo, algo así:
StratexWP7SoapClient StratexWP7 = new StratexWP7SoapClient(); //This is my web service
SPAuthBridge SharePointAuth;
public MainPage()
{
InitializeComponent();
(...)
SharePointAuth = new SPAuthBridge(SiteUrl, Username, Password);
SharePointAuth.OnAuthenticated += new SPAuthBridge.OnAuthenticatedHandler(SharePointAuth_OnAuthenticated);
if (!string.IsNullOrEmpty(Password))
SharePointAuth.Authenticate();
else
MessageBox.Show("The application should be configured before use.");
}
void SharePointAuth_OnAuthenticated(bool Success)
{
if (!Success)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{ MessageBox.Show("There was an error on the authentication procedure. Please check the configuration."); });
return;
}
StratexWP7.CookieContainer = SharePointAuth.cookieJar; //This is all you have to do to connect your web service. \m/ O.O \m/
HookEvents();
RequestData();
}
Es precioso
(Por cierto, las gráficas son de AmCharts)
viernes, 1 de julio de 2011
Depurando aplicaciones en el teléfono después de actualizar a “Mango”
Acabo de actualizar el teléfono a Windows Phone 7.1 codename “Mango”. No puedo decir mucho porque no he tenido tiempo de probarlo, pero sí que puedo decir que es más rápido.
Algunas de las nuevas funcionalidades no estan implementadas y tienen un cartelito de “Coming soon!” pero no es esto lo que quiero contar hoy.
El caso es que después de actualizar no podía depurar las aplicaciones en el teléfono como antes. El emulador se lanzaba automáticamente (y esto me cascaba todas las máquinas vituales devBox que tenía corriendo en el momento.
Después de un ratito mirando me di cuenta de que era más facil de lo que pensaba… Hay un dropdown ahí arriba para que elijas cómo quieres debugarÑ
Solo tienes que elegir Windows Phone Device y enmi caso desbloquear otra vez el teléfono con la Developer Phone Registration tool y a correr!
Algunas de las nuevas funcionalidades no estan implementadas y tienen un cartelito de “Coming soon!” pero no es esto lo que quiero contar hoy.
El caso es que después de actualizar no podía depurar las aplicaciones en el teléfono como antes. El emulador se lanzaba automáticamente (y esto me cascaba todas las máquinas vituales de
Después de un ratito mirando me di cuenta de que era más facil de lo que pensaba… Hay un dropdown ahí arriba para que elijas cómo quieres debugarÑ
Solo tienes que elegir Windows Phone Device
jueves, 21 de abril de 2011
Depurando aplicaciones de Windows Phone 7
Finalmente conseguí cargar y depurar mi aplicación en mi teléfono, pero no fue tan fácil...
Antes de nada encontré las instrucciones en esta página http://msdn.microsoft.com/en-us/library/ff941089(v=vs.92).aspx#BKMK_Register
Ahí dice que tienes que registrarte en el App Hub antes de poder hacer nada con tu móvil (y cuesta 100$) las palabras textuales son:
“You should register for membership as a Windows Phone developer before you begin creating applications because some development tasks, such as installing your application on a physical phone for testing, require App Hub membership”
Bien, esto significa que tienes que pagar 100$ antes de probar nada... paga antes, decide después. No puedo decir que me guste la filosofía.
Al final mi jefe se registró en el App Hub con su Live ID personal. Gran error. Sabíamos que podíamos tener hasta tres teléfonos de desarrollo, pero nadie nos dijo que todos ellos debían estar con la misma Live ID. Creíamos que se podrían invitar desarrolladores o algo así, pero no. Y no hay vuelta atrás no puedes cambiar tu suscripción a App Hub a otro Live ID... Tampoco estoy contento con esto.
¿Quieres saber cómo lo solucionamos? pues con una buena dosis de confianza por su parte.
Una vez que tienes registrada la Live ID al App Hub todo es fácil.
Conseguí desbloquear y registrar el teléfono usando la "Developer Phone Registration tool" http://msdn.microsoft.com/en-us/library/ff769508(VS.92).aspx… Bien, ¿y ahora que?
Pues ahora ya está todo preparado.
Si quieres ejecutar tu aplicación en tu móvil en cualquier momento tienes que desplegarla con la “Application Deployment” siguiendo las instrucciones de http://msdn.microsoft.com/en-us/library/gg588378(v=vs.92).aspx
O si prefieres puedes pulsar F5 en tu Visual Studio y poner la aplicación a correr en el teléfono y, finalmente... ¡Depurar!
Antes de nada encontré las instrucciones en esta página http://msdn.microsoft.com/en-us/library/ff941089(v=vs.92).aspx#BKMK_Register
Ahí dice que tienes que registrarte en el App Hub antes de poder hacer nada con tu móvil (y cuesta 100$) las palabras textuales son:
“You should register for membership as a Windows Phone developer before you begin creating applications because some development tasks, such as installing your application on a physical phone for testing, require App Hub membership”
Bien, esto significa que tienes que pagar 100$ antes de probar nada... paga antes, decide después. No puedo decir que me guste la filosofía.
Al final mi jefe se registró en el App Hub con su Live ID personal. Gran error. Sabíamos que podíamos tener hasta tres teléfonos de desarrollo, pero nadie nos dijo que todos ellos debían estar con la misma Live ID. Creíamos que se podrían invitar desarrolladores o algo así, pero no. Y no hay vuelta atrás no puedes cambiar tu suscripción a App Hub a otro Live ID... Tampoco estoy contento con esto.
Una vez que tienes registrada la Live ID al App Hub todo es fácil.
Conseguí desbloquear y registrar el teléfono usando la "Developer Phone Registration tool" http://msdn.microsoft.com/en-us/library/ff769508(VS.92).aspx… Bien, ¿y ahora que?
Pues ahora ya está todo preparado.
Si quieres ejecutar tu aplicación en tu móvil en cualquier momento tienes que desplegarla con la “Application Deployment” siguiendo las instrucciones de http://msdn.microsoft.com/en-us/library/gg588378(v=vs.92).aspx
O si prefieres puedes pulsar F5 en tu Visual Studio y poner la aplicación a correr en el teléfono y, finalmente... ¡Depurar!
Creando un Expander en Silverlight para Windows Phone
Hace unos días estaba migrando una aplicación a WP7 y me di cuenta de que el control Expander no estaba... Me instalé entonces el Silverlight for Windows Phone Toolkit pero me di cuenta de que tampoco había Expander allí.
No se me ocurría ninguna manera nueva de representar la información sin expanders así que tuve que crear una versión simplificada para la ocasión. El control se compone de un Grid, un StackPanel y un TextBlock.
Está muy limitado y no se supone que con esto se vaya a poder sustituir al Expander de toda la vida, pero quizás pueda ayudar a alguien por ahí.
El código XAP es:
Si el expander está plegado añado los elementos al StackPanel, si está desplegado los quito. Suena muy simple, pero no era capaz de hacerlo funcionar. El StackPanel se quedaba del mismo tamaño, pero vacío, sin hijos... feísimo.
Después de pasar un rato intentando encoger el StackPanel a manija cambiando el parámetro Heigh encontré el problema.
Estaba intentando borrar todos los elementos del StackPanel a la vez con Children.Clear y eso estaba volviéndolo loco. La solución era borrar los elementos dentro de Children de uno en uno.
El código para la clase Expander es algo así:
No se me ocurría ninguna manera nueva de representar la información sin expanders así que tuve que crear una versión simplificada para la ocasión. El control se compone de un Grid, un StackPanel y un TextBlock.
Está muy limitado y no se supone que con esto se vaya a poder sustituir al Expander de toda la vida, pero quizás pueda ayudar a alguien por ahí.
El código XAP es:
<Grid x:Name="LayoutRoot">
<Border VerticalAlignment="Top" BorderBrush="#FF929EB0" BorderThickness="1" CornerRadius="2" Background="#FFE9E9E9" Margin="5,2">
<Grid d:LayoutOverrides="Width">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="20"/>
<RowDefinition Height="Auto" MinHeight="5"/>
</Grid.RowDefinitions>
<TextBlock x:Name="Header" TextWrapping="Wrap" d:LayoutOverrides="Width" Foreground="#FF656565" Margin="15,2,0,0" VerticalAlignment="Top"/>
<StackPanel x:Name="ChildrenPanel" VerticalAlignment="Top" d:LayoutOverrides="Width" Margin="0,2,0,0" Grid.Row="1"/>
</Grid>
</Border>
</Grid>El truco está en añadir un TextBlock en la cabecera del expander y suscribirse al evento MouseLeftButtonUp del TextBlock para controlar el plegado y desplegado. También he añadido una propiedad Folded para manejar el estado del expander desde afuera. Si el expander está plegado añado los elementos al StackPanel, si está desplegado los quito. Suena muy simple, pero no era capaz de hacerlo funcionar. El StackPanel se quedaba del mismo tamaño, pero vacío, sin hijos... feísimo.
Después de pasar un rato intentando encoger el StackPanel a manija cambiando el parámetro Heigh encontré el problema.
Estaba intentando borrar todos los elementos del StackPanel a la vez con Children.Clear y eso estaba volviéndolo loco. La solución era borrar los elementos dentro de Children de uno en uno.
El código para la clase Expander es algo así:
public partial class Expander : UserControl
{
bool _Folded;
public bool Folded
{
get { return _Folded; }
set
{
_Folded = !value;
ExpanderSwitch();
}
}
List ChildrenList;
public Expander()
{
// Required to initialize variables
InitializeComponent();
ChildrenList = new List();
Header.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(UserActivity_MouseLeftButtonUp);
}
void UserActivity_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
ExpanderSwitch();
}
private void ExpanderSwitch()
{
if (Folded)
{
foreach (var child in ChildrenList)
ChildrenPanel.Children.Add(child);
}
else
{
if (ChildrenList.Count == 0)
foreach (var item in ChildrenPanel.Children)
ChildrenList.Add(item);
while (ChildrenPanel.Children.Count > 0)
ChildrenPanel.Children.RemoveAt(0);
}
_Folded = !_Folded;
}
} Y para usarlo solo tienes que añadir el control:<Grid x:Name="LayoutRoot">
<this:Expander x:Name="UserNews" />
</Grid>Y en el code behind puedes hacer algo como esto: UserNews.Header.Text = GetHeader(News[0]);
foreach (FrameworkNews news in News)
UserNews.ChildrenPanel.Children.Add(new NewsDetail(news.Link, GetDetail(news), news.Where));
UserNews.Folded = true;Si tienes tiempo puedes añadir imágenes y animaciones al expander, y también un mejor "control del despliegue"... Yo no puedo dedicarle más tiempo, aunque me encantaría.... Una pena.
Suscribirse a:
Entradas (Atom)
No hay comentarios:
Publicar un comentario