Статьи

Миграция приложений Android на Windows Phone 7

В этой статье вы познакомитесь с подходом к переносу приложения, написанного на Java, с использованием Eclipse для Android, на Windows Phone 7 с использованием Visual Studio, C # и Silverlight. Вы ознакомитесь с полным приложением для Android и узнаете, как перенести его пользовательский интерфейс и код на Windows Phone 7. Вы увидите, как вы можете использовать Interoperability Bridge от Microsoft для помощи в переводе API.

Приложение Android StckPckr

Приложение представляет собой забавный небольшой инструмент, который просматривает историю цен акций и использует техническую аналитику для акций, чтобы определить, подходящее ли время для их покупки или для продажи. Обратите внимание, что это просто демонстрация, и вы не должны основывать свои инвестиционные решения на этом.

Он рассматривает историю цен акций за последние 2 месяца и вычисляет так называемые «полосы Боллинджера» для акций. Они предоставляют индикатор для статистически значимых значений для акций. Индикатор того, что это может быть хорошей возможностью для покупки акций, поскольку их цена относительно низкая, появляется, когда акция находится в нижней части полос. Точно так же, если его цена относительно высока, он будет на вершине полосы.

Приложение позволит вам ввести тикер акций и рассчитать диапазон. Затем он преобразует текущую цену акции в позицию в пределах этой полосы, где 0 внизу и 100 сверху. Он будет использовать это для управления ползунком в пользовательском интерфейсе, чтобы показать вам относительную позицию цены.

Так, например, на рисунке 1 показан расчет для AAPL 14 ноября 2011 года, запущенного на виртуальном устройстве Android 2.3.3. Он основан на расчете цены закрытия предыдущего дня. Для Apple это было $ 384,62. Сегодня, когда я запускаю приложение, акция торгуется за $ 379,77, показывая, что методология довольно точная!

1_Android_StckPckr_App

1 Android-приложение StckPckr

Это приложение является хорошим, простым примером приложения для переноса, потому что оно:

  1. Имеет пользовательский интерфейс, определенный в XML, в Main.xml.
  2. Использует код для инициализации некоторых частей пользовательского интерфейса, например, устанавливает ползунок состояния по умолчанию на «50», а также использует код для динамического обновления пользовательского интерфейса, изменяя значение ползунка после завершения аналитики.
  3. Использует сетевой стек для получения информации через Интернет и требует, чтобы манифест предоставил разрешения, позволяющие это сделать.
  4. Использует чистую Java для математики, участвующей в вычислении данных.

Независимо от того, чем занимается ваше приложение, большинство приложений будет обладать некоторыми из этих функциональных возможностей, поэтому, если вы сможете портировать это приложение, вы уже на пути к портированию любого приложения!

Начало работы с Windows Phone

На данный момент, я предполагаю, что у вас уже есть Eclipse, Android SDK и все остальное, что вам нужно для разработки Android. Если вы этого не сделаете, перейдите на портал разработчиков Android и настройте себя. Мы рассмотрим Eclipse с приложением StckPckr чуть позже.

Для разработки под Windows Phone вы можете использовать Visual Studio Professional, если он у вас уже есть, или, если нет, бесплатный Visual Studio 2010 Express для Windows Phone отлично справляется со своей задачей. Вы можете скачать это от Microsoft, используя ссылку.

Если вы только начинаете, между бесплатной и профессиональной версиями Visual Studio не так много серьезных различий, поэтому не беспокойтесь, если вы просто хотите использовать бесплатную версию. Основное различие, которое вы можете увидеть, следуя этой статье при использовании Visual Studio Express, заключается в том, что вам доступно меньше шаблонов приложений.

Для начала, после того как вы установили Visual Studio, запустите ее и в меню «Файл» выберите «Новый проект». Вы должны увидеть список типов шаблонов. Выберите «Silverlight для Windows Phone» слева и «Приложение для Windows Phone» из списка доступных типов доступных типов. Смотрите рисунок 2.

2_Launch_Windows_Phone_App

2 Запустите приложение для Windows Phone

Дайте вашему приложению имя StckPckr7 и нажмите ОК. Выберите Windows Phone 7.1 в качестве целевой ОС и нажмите ОК.

Visual Studio создаст для вас новый проект Windows Phone 7 и загрузит пользовательский интерфейс в конструктор. Это даст вам визуальное представление вашего пользовательского интерфейса и разметку XML, определяя его рядом. Microsoft называет пользовательский интерфейс XML Markup «XAML», что означает «язык разметки приложений XML». Смотрите рисунок 3.

3_Visual_Studio_Designing_UI

3 Visual Studio Проектирование пользовательского интерфейса

Как разработчик Android, использующий Eclipse, вам придется настраивать несколько AVM на основе разных ОС или типов устройств, на которые вы ориентируетесь, от телефонов Android 2.1 до планшетов Android 4.0. Поскольку в телефонах с Windows относительно мало различий, эмуляция не требует такой настройки. Просто нажмите кнопку Run (или F5), чтобы запустить приложение в эмуляторе, как показано на рисунке 4.

4_Windows_Phone_Emulator

4 Windows Phone Emulator

Отлично, теперь у вас есть все необходимое для начала. Итак, давайте вернемся к Eclipse и посмотрим на приложение для Android.

Портирование пользовательского интерфейса Android на XAML

Лучше всего начать с XML, определяющего пользовательский интерфейс для приложения StckPckr, и перенести его в XAML. В Eclipse в папке app / res / layout вы увидите файл с именем «Main.xml». Откройте его, и вы, вероятно, увидите его в визуальном дизайнере, как на рисунке 5.

5_StckPckr_UI_Android_Eclipse

5 StckPckr UI Android Eclipse

Я считаю, что представление Outline справа на этой диаграмме особенно полезно. Он показывает класс каждого элемента управления в этом пользовательском интерфейсе, который, как вы можете видеть в этом случае:

  • LinearLayout
    • textView1 — «Добро пожаловать в StckPckr»
    • linearLayout1
      • textView2 — «Enter Ticker»
      • editText1
      • button1 — «Go»
    • SeekBar1
    • textView3 — ‘- Купить Продать-‘

Первый LinearLayout является корнем представления и содержит 4 элемента управления: TextView с надписью «Welcome to StckPckr»; элемент управления LinearLayout, который содержит несколько элементов управления самостоятельно; бар поиска; и другой вид текста. Эти элементы управления расположены вертикально.

LinearLayout, называемый linearLayout1, является дочерним по отношению к первому, но он ориентирован по горизонтали и содержит TextView, поле EditText и Button.

Каждый из этих элементов управления имеет соответствующий элемент управления в Windows Phone 7, и отличный способ узнать, что они из себя представляют, — использовать API-интерфейс сопоставления, предоставляемый Microsoft.
Так, например, найдите элемент управления LinearLayout, используя инструмент сопоставления API. Он сопоставит вас с чем-то, называемым «StackPanel», и если вы посмотрите на его ГОРИЗОНТАЛЬНЫЕ и ВЕРТИКАЛЬНЫЕ перечисления, вы увидите, что они соответствуют перечислению в Windows Phone 7, называемому «Ориентация». Точно так же вы можете увидеть следующие отображения:

  • Кнопка -> Кнопка
  • EditText -> TextBox
  • SeekBar -> Слайдер

TextView отсутствует в текущем воплощении API сопоставления, но в Windows Parlance это называется TextBlock. Таким образом, грубый перевод вашего интерфейса должен выглядеть так:

  • StackPanel (Orientation = ”Vertical”)
    • TextBlock — «Добро пожаловать в StckPckr7»
    • StackPanel (ориентация = «горизонтальный»)
      • TextBlock — «Enter Ticker»
      • Текстовое окно
      • Кнопка — «Перейти»
    • TextBlock — ‘- Купить Продать -‘

С небольшим поиском вы можете найти и другие вкусности. Например, выравнивание текста в Android выполняется с использованием ‘gravity’, и вы можете видеть, что, например, элемент управления TextView использует его следующим образом:

<TextView android:id="@+id/textView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="Welcome to StckPckr" android:textAppearance="?android:attr/textAppearanceLarge" /> 

Быстрый поиск API-сопоставления показывает, что для многих элементов управления Android Gravity отображается на Alignment. Аккуратная часть intellisense в Visual Studio заключается не в том, что он запускается путем сопоставления вводимых символов с первой частью свойства, а вместо этого делает это с любой частью свойства. Так, если, например, вы редактируете TextBlock и вводите «Align», вы увидите, что «TextAlignment» отображается как доступное свойство, и это то, что вы будете использовать для центрирования текста по способу гравитации. делает это в Android.

Редактирование вашего XAML

Редактор XAML в Visual Studio очень дружелюбен и предоставляет intellisense и автозаполнение, чтобы помочь вам заполнить ваши теги. Посмотрите на это в Visual Studio, и ваш MainPage.xaml будет выглядеть примерно так:

 <phone:PhoneApplicationPage x:Class="StckPckr7.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid> </Grid> <!--Sample code showing usage of ApplicationBar--> <!--<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="MenuItem 1"/> <shell:ApplicationBarMenuItem Text="MenuItem 2"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>--> </phone:PhoneApplicationPage> 

Выделенная часть — это место, где вы будете рисовать свой интерфейс Остальное — это пользовательский интерфейс, предоставляемый вам ОС, но вы должны отредактировать элементы управления TextBlock, которые определяют «Мое приложение» и «имя страницы», на что-то более дружелюбное.

Теперь в вашей области контента, сетке с именем ContentPanel, вы можете определить пользовательский интерфейс, как вы выяснили выше. Когда вы вводите теги, intellisense помогает вам в этом и помогает легко находить нужные свойства. Это должно выглядеть примерно так:

 <Grid Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel Orientation="Vertical"> <TextBlock Text="Welcome to StckPckr7 for Windows Phone"></TextBlock> <StackPanel Orientation="Horizontal" Margin="0,20,0,0"> <TextBlock Text="Enter a Ticker"></TextBlock> <TextBox Text="" Width="200"></TextBox> <Button Content="Go"></Button> </StackPanel> <Slider Maximum="100" Value="50" Margin="0,20,0,0"></Slider> <TextBlock Text=" -- Buy Sell --" TextAlignment="Center"></TextBlock> </StackPanel> </Grid> 

Это даст вам интерфейс, очень похожий на Android. Нажмите F5, чтобы запустить его в эмуляторе. Вы увидите что-то вроде рисунка 6.

6_Running_Ported_UI

6 Запуск перенесенного интерфейса

Очевидно, что это не очень красивый интерфейс, но он показывает, как начать работу с портированием. Изменяя свойства или используя Expression Blend в качестве инструмента WYSIWYG, вы можете сделать интерфейс намного приятнее. Но ради краткости мы оставим это визуально до конца этой статьи.

Есть еще одна вещь, которую вам нужно отредактировать в вашем XAML, прежде чем продолжить работу с кодом, а именно дать имена каждому из элементов управления. В Android вы используете android:id в декларации XML. В Windows Phone 7 вы используете Name , например так:

 <StackPanel Orientation="Vertical"> <TextBlock Text="Welcome to StckPckr7 for Windows Phone"></TextBlock> <StackPanel Orientation="Horizontal" Margin="0,20,0,0"> <TextBlock Text="Enter a Ticker"></TextBlock> <TextBox Name="TextBox1" Text="" Width="200"></TextBox> <Button Name="Btn1" Content="Go"></Button> </StackPanel> <Slider Name="Slider1" Maximum="100" Value="50" Margin="0,20,0,0"></Slider> <TextBlock Text=" -- Buy Sell --" TextAlignment="Center"></TextBlock> </StackPanel> 

Вам не нужно называть все элементы управления, только те, к которым вы хотите обратиться в коде. Вы увидите, как это сделать, в следующем разделе.

Портирование кода

Шаг 1. Понимание того, как связаны View View и View Code

В Android вы обычно пишете свой код как активность, которая поддерживает представление. Когда вы компилируете, генерируется R.java, и код для представления, находящегося в Activity, должен загрузить пользовательский интерфейс для своего представления из R.java, используя такой код:

 setContentView(R.layout.main); 

Где, в этом случае, представление определяется с помощью Main.xml .

Код для представления Windows Phone 7 немного более тесно связан с определением представления. Как правило, если у вас есть представление с именем MainPage.xaml , вы напишите код для него в MainPage.xaml.cs . Если вы посмотрите на обозреватель решений для своего проекта, вы увидите это. Смотрите рисунок 7.

7_Connecting_XAML_Code_CS

7 Подключение XAML Code CS

Это процесс, который разработчики Microsoft называют «Code-behind», где код страницы находится «за» страницей. Вы можете вызывать файл кода как угодно, если класс, к которому он компилируется, распознается страницей. Если вы посмотрите прямо вверху страницы XAML, вы увидите, что она определяет свой класс кода, используя узел x:Class . Итак, в этом случае вы увидите:

 x:Class="StckPckr7.MainPage" 

Это означает, что класс MainPage содержит код для этого представления. Взгляните на MainPage.xaml.cs , и вы увидите, что он определяет класс MainPage :

 public partial class MainPage : PhoneApplicationPage { } 

Итак, теперь вы можете написать свой код в этом классе, и он будет обрабатывать пользовательский интерфейс, определенный в MainPage.xaml .

Шаг 2. Обработка приложения или просмотр событий жизненного цикла

В приложении Android вы, как правило, выполняете любую инициализацию вашего интерфейса на основе onCreate функции onCreate . Эта функция вызывается, когда ваше приложение создает представление, но до того, как оно его отображает. Таким образом, вы хотите поместить туда код, который инициализирует ваши компоненты пользовательского интерфейса (такие как установка максимума Seekbar и текущих точек), чтобы они были готовы до их отрисовки. Вот полный код onCreate в нашем приложении.

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final EditText edt = (EditText)findViewById(R.id.editText1); seek = (SeekBar)findViewById(R.id.seekBar1); seek.setMax(100); seek.setProgress(50); Button btn = (Button)findViewById(R.id.button1); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { String strTicker = edt.getText().toString(); try{ analyzeTicker(strTicker); } catch(Exception ex) { // Do nothing } } }); } 

Если вы посмотрите на Activity.onCreateView с помощью инструмента API Mapping, вы увидите, что эквивалент в Windows Phone 7 называется Application_Launching. Это правда, но не совсем верно.

Application_Launching запускается до того, как приложение загрузится и отобразит его пользовательский интерфейс. Но если в вашем пользовательском интерфейсе есть класс, лежащий в его основе, лучшим способом управления инициализацией этого класса было бы сделать это в конструкторе этого класса. Таким образом, объекты пользовательского интерфейса могут быть «локальными» переменными вместо «глобальных», какими они должны быть, если бы вы обращались к ним из глобального класса. Так лучше объектно-ориентированное программирование. Для справки вы должны изучить события жизненного цикла приложения. Они заглушены для вас в Visual Studio в App.xaml и App.xaml.cs

Но для целей этого приложения любая инициализация пользовательского интерфейса должна выполняться в конструкторе MainPage() . В нашем приложении для Android код делал три вещи:

  • Получите ссылку на EditText и назовите его edt, чтобы мы могли ссылаться на него в коде
  • Получить ссылку на SeekBar и вызвать ее поиск, чтобы мы могли ссылаться на нее в коде
  • Получите дескриптор кнопки, назовите ее btn и добавьте обработчик события OnClickListener

В нашем Windows Phone 7 этот процесс немного проще

  • Нам не нужно получать ссылку на TextBox, чтобы ссылаться на него в коде. Называя его с помощью Name в XAML, мы уже можем получить к нему доступ, используя имя TextBox1
  • Точно так же мы можем ссылаться на Slider (соответствует SeekBar), используя его имя как определено в XAML
  • Точно так же мы можем ссылаться на Button напрямую по ее имени, но нам все еще нужно добавить обработчик события для нее.

Если вы никогда ранее не пользовались Visual Studio, внимательно следуйте следующим шагам, чтобы увидеть одну из функций автоматического завершения кулера. Откройте MainPage.xaml.cs и поместите курсор в функцию конструктора.

Наберите ‘bt’, и вы увидите меню с Btn1 в нем. Он признает, что у вас есть этот объект. Нажмите клавишу TAB, и она будет заполнена для вас.

Введите точку «.», А затем буквы «C», «L» и «I». Вы увидите, что меню следует за вашим набором, и теперь «Click» будет в верхней части списка. Нажмите TAB еще раз, чтобы заполнить его.

Теперь вот действительно классная часть. Введите ‘+ =’, и появится небольшое серое поле, указывающее на то, что вам нужен новый обработчик Routed Event. Нажмите клавишу TAB, и код будет вставлен. Нажмите TAB еще раз, и полная заглушка для обработчика событий будет сгенерирована и вставлена ​​для вас! Это делает это намного проще, чем запоминание синтаксиса функции обработчика событий и возвращаемых типов. Ваш код должен выглядеть следующим образом:

 public MainPage() { InitializeComponent(); Btn1.Click += new RoutedEventHandler(Btn1_Click); } void Btn1_Click(object sender, RoutedEventArgs e) { throw new NotImplementedException(); } 

Это намного меньше кода, чем вы имели в деятельности Android. Теперь давайте реализуем обработчик события Click для кнопки. Во-первых, давайте снова посмотрим код Java из версии Android:

 btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { String strTicker = edt.getText().toString(); try{ analyzeTicker(strTicker); } catch(Exception ex) { // Do nothing } } }); 

Всякий раз, когда пользователь нажимает кнопку, обработчик событий считывает содержимое EditText, создает из него строку и передает ее для анализа тикера. Делать это в C # очень похоже. Обновите Btn1_Click на следующее:

 void Btn1_Click(object sender, RoutedEventArgs e) { String strTicker = TextBox1.Text; analyzeText(strTicker); } 

Вы можете использовать try..catch() в C # точно так же, как вы используете его в Java. Я просто опустил это здесь, потому что это не является необходимым в C # версии функции analyzeText которую вы увидите далее.

Шаг 3. Обработка чистого Java-кода

Итак, до сих пор вы видели, как сначала перенести ваш пользовательский интерфейс, определенный в XML, на интерфейс на основе XAML. Затем вы увидели, как XAML и C # работают вместе, чтобы обеспечить выделение кода для View, подобно действиям Java. Затем вы увидели часть жизненного цикла приложения, как запустить код при запуске представления.

Наконец, вы увидели, как ссылаться на элементы управления пользовательского интерфейса из вашего кода, и «подключать» обработчики событий, чтобы вы могли писать код, который реагирует на события в приложении. Наконец, мы рассмотрим сущность Java-приложения, а именно код, который получает входные данные пользователя, извлекает данные из Интернета, анализирует их и использует этот анализ для предоставления обратной связи пользователю.

3.1. Создание URI финансов Yahoo

Код Java для этого приложения можно разбить на 3 этапа. Первый — создать URI для службы данных. В этом случае мы используем финансовые данные Yahoo, которые извлекаются как CSV (значения, разделенные запятыми) с помощью HTTP-вызова. Есть хороший учебник для этого синтаксиса здесь: http://www.gummy-stuff.org/Yahoo-data.htm

Вот код Java для этого:

 // Create the Yahoo URI Calendar today = Calendar.getInstance(); int today_day = today.get(Calendar.DATE); int today_month = today.get(Calendar.MONTH) + 1; int today_year = today.get(Calendar.YEAR); Calendar start = Calendar.getInstance(); start.add(Calendar.MONTH, -2); int start_day = start.get(Calendar.DATE); int start_month = start.get(Calendar.MONTH) + 1; int start_year = start.get(Calendar.YEAR); StringBuilder uri = new StringBuilder(); uri.append("http://ichart.finance.yahoo.com/table.csv"); uri.append("?s=").append(strTicker); uri.append("&a=").append(start_month); uri.append("&b=").append(start_day); uri.append("&c=").append(start_year); uri.append("&d=").append(today_month); uri.append("&e=").append(today_day); uri.append("&f=").append(today_year); uri.append("&g=d"); 

Он находит текущую дату и преобразует ее в значения дня, месяца и года, а затем дату 2 месяца назад, делая то же самое, и вставляя их в StringBuilder, который создает URI.

Хотя в Windows Phone 7 есть объект «Календарь», на самом деле это элемент управления пользовательского интерфейса, представляющий календарь. Так что не поддавайтесь этому! В C # эквивалентом Java Calendar является класс DateTime.

3.2. Создание HTTP-запроса для получения данных и чтение ответа

Следующим шагом является то, что код Java Android создает объект HttpClient для управления соединением со службой, объект HttpGet, представляющий действие, которое будет выполнено для этой службы (запрос HTTP обычно представляет собой POST или GET, и в этом случае case это GET) и объект HttpResponse для выполнения команды на клиенте и чтения ответа.

 HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI(uri.toString())); HttpResponse response = client.execute(request); 

Используя API mapper, я обнаружил, что класс WebClient может быть близок к тому, что я хочу сделать для HttpClient. WebClient также имеет асинхронный вызов для чтения содержимого URL, поэтому я использовал следующий код:

 WebClient client = new WebClient(); client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted); client.OpenReadAsync(new Uri(uri.ToString())); 

С помощью вставки кода, предоставляемой клавишей TAB при наборе второй строки, у меня была создана функция обработчика событий. Таким образом, в этом случае, когда телефон считывает данные из URI, он перезванивает этой функции, таким образом не блокируя никакие потоки.

На этом этапе в Java вы будете использовать BufferedReader для чтения данных построчно. Каждая строка CSV, поэтому, когда она читается как строка, вы можете «разделить» ее запятыми. Элемент данных, который мы хотим (цена закрытия), является пятым элементом, поэтому после разделения скрипта он добавляется в ArrayList. Вот код:

 in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String line = ""; while ((line = in.readLine()) != null) { String[] rowData = line.split(","); Double dummy = new Double(rowData[4]); nTotal+=dummy; closePrices.add(dummy); } 

В C # мы делаем то же самое. Некоторые изменения должны были быть сделаны, потому что читатель был назван «в» в Java. Это зарезервированное слово в C #, поэтому мы не можем его использовать. Кроме этого, код очень похож, за исключением того, что C # не поддерживает ArrayList для динамических массивов, поэтому вместо него использовался List<Double> :

 void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { System.IO.StreamReader instream = new System.IO.StreamReader(e.Result); instream.ReadLine(); //Read the first line String line; List<Double> closePrices = new List<Double>(); while ((line=instream.ReadLine())!=null) { string[] rowData = line.Split(','); Double dummy = new Double(); dummy = Convert.ToDouble(rowData[4]); closePrices.Add(dummy); } instream.Close(); } 

3.3 Обработка данных

Последний шаг заключается в анализе данных, путем расчета полос Боллинджера, определения их конверта, а затем выяснения, где в этом конверте находится текущая цена, в процентах, при этом нижняя точка равна 0%, а верхняя часть равна 100%.

Объяснение статистического анализа, стоящего за этим, выходит за рамки данной статьи, но в двух словах, вычисляется среднее значение по диапазону, а затем из этого рассчитывается стандартное отклонение. Верхняя полоса — это среднее + 2 стандартных отклонения, нижняя — среднее значение — 2 стандартных отклонения.

Здесь Java и C # очень похожи, и из кода вы увидите, что требовались только незначительные изменения — в основном потому, что программа C # использует List<Double> вместо списка массивов, поэтому его API немного отличается, и потому что это не требует приведения, чтобы получить переменные или нет.

Вы увидите, что библиотеки Math практически идентичны, с Java ‘Math.pow’, имеющим эквивалент ‘Math.Pow’ в C #, и похожим для ‘Math.sqrt’ и ‘Math.Sqrt’. Вот код Java:

 Double nAverage = nTotal/closePrices.size(); Double sum=0.0; for (int i=0; i<closePrices.size(); i++) { sum+= Math.pow((Double) closePrices.get(i) - nAverage, 2); } Double nDeviation = Math.sqrt(sum/(closePrices.size()-1)); Double bollingerTop = nAverage + (2*nDeviation); Double bollingerBottom = nAverage - (2*nDeviation); int nToday = closePrices.size()-1; Double bCloseToday = (Double) closePrices.get(nToday); Double range = bollingerTop - bollingerBottom; Double value = bCloseToday - bollingerBottom; Double score = 100*value/range; seek.setProgress(score.intValue()); 

А вот и C #:

 Double nAverage = nTotal / closePrices.Count; Double sum = 0.0; for (int i = 0; i < closePrices.Count; i++) { sum += Math.Pow(closePrices[i] - nAverage, 2); } Double nDeviation = Math.Sqrt(sum / (closePrices.Count - 1)); Double bollingerTop = nAverage + (2 * nDeviation); Double bollingerBottom = nAverage - (2 * nDeviation); int nToday = closePrices.Count - 1; Double bCloseToday = closePrices[nToday]; Double range = bollingerTop - bollingerBottom; Double value = bCloseToday - bollingerBottom; Double score = 100 * value / range; Slider1.Value = score; 

Так что теперь, если я запускаю версию приложения для Windows Phone 7 и набираю AAPL, как я делал с Android, я получаю те же результаты. Смотрите рисунок 8.

8_Ported_Application

8 Портированное приложение

Резюме

В этой статье вы увидели, как переносить приложение Android с Java в Eclipse на Windows Phone 7 с помощью Visual Studio. Вы узнали о веб-сайте мостов взаимодействия Windows Phone и увидели, как его можно использовать для понимания парадигм Windows для элементов управления и объектов Java. Вы увидели, как пользовательский интерфейс XML можно перенести в XAML, а затем изучили, как жизненный цикл приложения и события взаимодействовали в Visual Studio. Наконец, вы написали код, который обрабатывал пользовательский ввод и вывод, и увидели, как приложение может работать на Windows Phone 7.