Bài 6: Xây dựng giao diện với XAML trong Windows Phone


Từ bài 1 ->bài 5 các bạn đã biết được cách thức tạo 1 Project Windows phone, cách sử dụng Emulator, đăng ký lập trình với thiết bị thật cũng như hiểu được vòng đời của một ứng dụng Windows phone như thế nào.

Từ Bài 6 trở đi Tui sẽ hướng dẫn các bạn cách thức lập trình với Windows Phone 8.1 Silverlight, Tui sẽ cố gắng tách từng phần nhỏ theo thứ tự từ dễ lên khó để giúp các bạn dễ nắm bắt cũng như có thể tự xâu chuỗi lại thành một hệ thống để có thể tiến hành viết được trọn vẹn một ứng dụng thực tế nào đó.

Trên internet có rất nhiều website hướng dẫn lập trình về Windows Phone 8.1 Silverlight các bạn có thể tham khảo,  tuy nhiên Tui sẽ hướng dẫn theo cách của Tui các bạn có thể chấp nhận hoặc không chấp nhận, nhưng dù sao các bạn cũng phải hiểu được căn cơ của Windows Phone 8.1 thì mới bắt tay lập trình tốt được, không quan trọng là đọc trang nào.

Trong bài 6: Xây dựng giao diện với XAML trong Windows Phone tui sẽ trình bày các phần liên quan tới XAML như sau:

1) Cách thức làm việc với XAML

2) Cách sử dụng Brush

3) Cách sử dụng Resource và Style

4) Và phần cuối cùng là Template.

Các bạn cần hiểu XAML trong Windows Phone vì khi bắt đầu new 1 project Helloworld là bạn để nhìn thấy ngay cấu trúc XAML của Windows Phone rồi. Nếu bạn đã có kiến thức về XML thì XAML cũng có vẻ tương tự nhưng võ công cao hơn 1 bậc.

Windows Phone sử dụng  XAML làm đặc thù cho phần thiết kế giao diện, bạn có thể sử dụng trực tiếp Visual Studio hoặc công cụ Microsoft Expression Blend để thiết kế (thường trong quá trình cài đặt Visual Studio nó đã đính kèm công cụ này rồi).

Bây giờ ta bắt đầu tìm hiểu XAML với phần đầu tiên:

1) Cách thức làm việc với XAML

XAML là gì?

-XAML (Extensible Application Markup Language) – phát âm zammel.

XAML là một ngôn ngữ đánh dấu khai báo tương tự như XML, nó được sử dụng để tạo giao diện tương tác với người dùng. Mỗi một phần tử trong XAML (tag element) đại diện cho một đối tượng (Object). XAML giúp ta trực quan hóa giao diện cũng như có khả năng lưu trữ hiển thị Data Source cũng như Custom Object. Bạn có thể để ý là mỗi một Project bạn tạo ra đều có một file MainPage.xaml đó chính là màn hình khởi động mặc định khi chạy ứng dụng cho phép người sử dụng tương tác.

Microsoft đã tách thành 2 phần riêng biệt: Phần xaml để thiết kế phần xaml.cs để lập trình (có thể gọi là logic runtime) giúp ta nâng cao khả năng tùy biến các control. Bạn có thể tưởng tượng rằng XAML thực chất là một định dạng XML mà thôi (Có phần mở rộng là .xaml).

Ví dụ về trang MainPage.xaml:


<phone:PhoneApplicationPage

x:Class="LearnXAML.MainPage"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

FontFamily="{StaticResource PhoneFontFamilyNormal}"

FontSize="{StaticResource PhoneFontSizeNormal}"

Foreground="{StaticResource PhoneForegroundBrush}"

SupportedOrientations="Portrait" Orientation="Portrait"

shell:SystemTray.IsVisible="True">

…

</phone:PhoneApplicationPage>

 XAML Namespace?

Thường mỗi trang XAML có khai báo các namespace với một prefix ngắn gọn mang tính gợi nhớ để giúp Ta dễ dàng lập trình cũng như truy suất các thông tin trong namespace.

Theo Tui thì có 2 lý do chính để chúng ta tạo namespace và đặt prefix name cho Namespace:

- Do tên Namespace quá dài và phức tạp.

- Do có nhiều lớp trùng tên nên cần đưa vào các Namespace khác nhau.

Việc sử dụng prefix (có thể hiệu đại khái là tên gì đó ngắn gọn đại diện cho Namespace) sẽ giúp chúng ta lập trình nhanh chóng.

Nếu quan sát kỹ ngay trang MainPage.xaml là bạn có thể phát hiện ra cách khai báo sử dụng namespace, prefix:

wp6_1Ta có cú pháp như sau:

wp6_2xmlns là từ khóa (tức là phải viết y xì vậy đó)

clr-namespace là từ khóa (tức là phải viết y xì vậy đó)

local là prefix (tức là tên ta muốn đặt đại diện cho CLR Namespace Name), thường thì ta nên đặt mang tính gợi nhớ.

Bạn phải nhớ công thức này để qua các bài tập tiếp theo Tui sẽ sử dụng lại (cụ thể trong việc sử dụng thư viện Windows Phone Toolkit)

Sau đây Tui sẽ làm một ví dụ về cách tạo 2 lớp MyButton (tức là cùng tên) nhưng nằm ở 2 namespace khác nhau, sau đó Tui sẽ minh họa cách sử dụng 2 MyButton này với công thức ở trên.

Lớp MyButton thứ nhất (mặc định có nền đỏ) tui cho nó nằm trong namespace tên tranduythanh.com, Lớp MyButton thứ nhì (mặc định có màu Xanh) tui cho nó nằm trong namespace caphe.net.

Tức là 2 MyButton này tui sẽ kế thừa từ Button của Microsoft và hiệu chỉnh lại theo thông số mà tui mô tả ở trên.

Bạn new một Project tên LearnNamespace:

wp6_3Bạn thấy ở trên Tui tô xanh file MyButton.cs (File này sẽ chứa 2 class MyButton nằm ở 2 Namespace khác nhau), bạn tạo file này như sau:

- Bấm chuột phải vào Project/ Chọn Add/ Class…:

wp6_4Màn hình Add New Item hiển thị ra như bên dưới, bạn chọn Class ở mục số 1, rồi đặt tên cho tập tin là MyButton ở mục số 2, sau đó bấm nút Add để tạo file này.

wp6_5Sau khi tạo xong bạn Double click vào MyButton.cs để tiến hành coding như sau:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//thêm thư viện này để kế thừa Button
using System.Windows.Controls;
//Thêm thư viện này để sử dụng SolidColorBrush
using System.Windows.Media;

namespace tranduythanh.com
{
public class MyButton:Button
{
public MyButton()
{
SolidColorBrush brush = new SolidColorBrush(Colors.Red);
this.Width = 400;
this.Height = 200;
this.Background = brush;
}
}
}
namespace caphe.net
{
public class MyButton:Button
{
public MyButton()
{
SolidColorBrush brush = new SolidColorBrush(Colors.Blue);
this.Width = 300;
this.Height = 100;
this.Background = brush;
}
}
}

Bạn thấy đấy ở trên có 2 Button trùng tên nhưng nằm ở 2 namespace khác nhau.

 

 

 

Bài 5: Vòng đời của ứng dụng Windows phone 8.1 và cách quản lý trạng thái


Trước khi sắn tay áo lập trình thì các bạn cũng cần hiểu được vòng đời của ứng dụng Windows phone và cách quản lý trạng thái của nó như thế nào, vì nêu như không hiểu được vòng đời của ứng dụng thì bạn sẽ gặp khó khăn khi gặp những trường hợp phải lưu cấu hình hệ thống, cũng như không biết vì sao ứng dụng của ta lại tự động mất hay các thông số bị reset….

Khác với Windows Phone 8.0, đối với Windows Phone 8.1 vòng đời của nó được thể hiện như sau (vẽ hình gì cũng được, đại khái là nó như vậy đó). Bạn cũng để ý là Windows Phone 8.0 khi nhấn nút Home rồi bấm nút Back thì nó sẽ không hiển thị lại ứng dụng; Windows Phone 8.1 thì khác nếu 1 ứng dụng đang chạy mà bạn nhấn nút Home sau đó bấm lại nút Back thì ứng dụng đó sẽ được hiển thị trở lại như cũ.

wp5_1- Bạn chú ý rằng với một ứng dụng Windows Phone thì nó có 3 trường hợp chính:

+  Một  là ứng dụng đang chạy (running) –> Người sử dụng quan sát thấy ứng dụng đầy đủ, tương tác được với ứng dụng, và ta cũng có thể gọi nó là Foreground Lifetime

+ Hai là ứng dụng không chạy (terminated)–> Tức là nó không còn sống trên cõi đời của Memory nữa

+ Ba là trạng thái tạm ngưng hoạt động (suspended) –> Ứng dụng vẫn còn sống trên cõi đời của Memory nhưng người sử dụng không tương tác được và nó sẽ bị rơi vào trạng thái Killable (tức là nó có thể bị hệ thống tước đoạt mạng sống bất cứ khi nào–> terminated). Ví dụ như ta đang thao tác với ứng dụng thì tự nhiên có cuộc gọi tới, thì ứng dụng cuộc gọi sẽ đè lên ứng dụng của ta –> ứng dụng của ta chuyển qua suspended.

Bạn cần phải phân biệt rõ trạng thái terminatedsuspended nó khác nhau như thế nào, và phải hiểu được lý do vì sao suspended lại có thể đưa ứng dụng vào trạng thái Killable? nó có một vài lý do chính sau:

1) Hệ thống thiếu RAM và cần thu hồi khi có những yêu cầu khác được ưu tiên hơn

2) Hoặc có thể thiết bị gần hết PIN, hệ thống cần kill ứng dụng để tiết kiệm PIN

3) Hoặc người sử dụng khởi động lại thiết bị.

4) Và những lý do gì đó mà ta không biết…

Khi ứng dụng rơi vào trạng thái Suspended thì nguy cơ nó bị terminated là rất cao, và nếu như không bị terminated thì nó cũng có thể bị reset các biến và đối tượng…

Như vậy một vài câu hỏi đặt ra cho vòng đời là:

1) Ta làm gì khi ứng dụng rơi vào trạng thái Suspended

2) Khi ứng dụng đang thực thi và đang chuyển đổi trạng thái thì các sự kiện gì sảy ra

3) quản lý các trạng thái thay đổi như thế nào.

————————————

Khi viết lệnh quản lý sự thay đổi trạng thái của ứng dụng thì thường ta xử lý ở 2 cấp độ:

- Cấp độ ứng dụng (xử lý trong App.xaml.cs) – có 4 sự kiện chính:


//Sự kiện này sẽ được triệu gọi khi ứng dụng được thực thi và nó sẽ không
//bị gọi lại khi ứng dụng reactived (tức là chỉ chạy 1 lần đầu tiên duy nhất)
private void Application_Launching(object sender, LaunchingEventArgs e)
{
string msg = "Application_Launching";
}

//Sự kiện nay được triệu gọi khi ứng dụng được Activated (người sử dụng tương tác được)
// Lầu đầu khi ứng dụng chạy (Application_Launching) nó sẽ không được gọi, các lần sau nó sẽ tiếp tục
//được triệu gọi nếu như nó được activated (chuyển từ Suspended sang Foreground Lifetime)
private void Application_Activated(object sender, ActivatedEventArgs e)
{
string msg = "Application_Activated";
}

//Sự kiện sẽ được triệu gọi khi ứng dụng bị đưa vào trạng thái Suspend
//--> tức là khi nó che khuất ứng dụng, người sử dụng không thể tương tác
//Và nó sẽ không được triệu gọi khi sự kiện Closing sảy ra
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
string msg = "Application_Deactivated";
}

//Sự kiện được triệu gọi khi ứng dụng chuyển qua trạng thái đóng (terminate)
//và nó sẽ không thực thi khi ứng dụng vào trạng hái Deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
string msg = "Application_Closing";
}

—>Ta thường lưu thông tin cấp ứng dụng trong sự kiện Application_Deactivated và khởi tạo lại thông tin trong sự kiện Application_Activated.

- Cấp độ trang (xử lý trong mỗi trang .xaml.cs) – có 2 sự kiện chính:


//Sự kiện sảy ra khi trang được hiển thị Foreground
//Ta thường khởi tạo lại giá trị được lưu trữ trong hàm này
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
if(localsetting.Values["data"]!=null)
{
txtData.Text = localsetting.Values["data"].ToString();
}
}
//sự kiện sảy ra khi trang bị đóng hoặc bị trang khác đè lên
//Ta thường lưu thông tin cấp độ trang trong hàm nay
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
localsetting.Values["data"] = txtData.Text;
}

Bạn cần chú ý thứ tự diễn ra các sự kiện:

- Đầu tiên sự kiện ở cấp độ ứng dụng sẽ sảy ra trước

- Sau đó mới tới sự kiện ở cấp độ trang.

tức là Nếu trong 1 Project bạn vừa xử lý trạng thái ở cấp độ ứng dụng và cấp độ trang, khi  ứng dụng bị suspended thì tuần  tự sảy ra như sau:

hàm Application_Deactivated sảy ra trước sau đó mới tới OnNavigatedFrom.

- Tui có cung cấp lệnh lưu và phục hồi thông tin ở trên, các bạn có thể áp dụng vào ứng dụng của mình.

Để các bạn có thể dễ dàng thực hành bài tập này thì làm theo từng bước như sau:

 Bước 1:

Tạo một Project tên “LearnLifeCycle” như hình chụp dưới đây:

wp5_2Chú ý là chọn “Blank App (Windows Phone Silverlight)”, từ này các ví dụ Tui sẽ sử dụng loại Project này.

 Bước 2:

Tạo thêm 2 trang Page2.xamlPage3.xaml như hình dưới đây:

wp5_3Để tạo mới 1 trang thì bạn chỉ cần bấm chuột phải vào Project chọn/ Add/ New Item:

wp5_4Màn hình Add New Item sẽ hiển thị ra như dưới đây:

wp5_5

Chọn các thông số như hình, rồi bấm nút Add bạn sẽ có kết quả như mong muốn (tạo được 1 trang mới). Tương tự như vậy bạn có thể thêm Page3.xaml vào ứng dụng.

Bước 3:

Tiến hành XAML và coding cho Mainpage.xaml như sau:

wp5_6Xử lý coding cho Mainpage:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using LearnLifeCycle.Resources;

namespace LearnLifeCycle
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();

// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
//Nếu còn về trước được
if (NavigationService.CanGoBack)
NavigationService.GoBack();//thì về trước
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
//xử lý chuyển qua trang mới
if(NavigationService.CanGoForward)
{
NavigationService.GoForward();
}
else
{
//tạo uri qua trang mới:
Uri newPage = new Uri("/Page2.xaml", UriKind.Relative);
//gọi lệnh chuyển trang
NavigationService.Navigate(newPage);
}
}
//Sự kiện sảy ra khi trang được hiển thị Foreground
//Ta thường khởi tạo lại giá trị được lưu trữ trong hàm này
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
if(localsetting.Values["data"]!=null)
{
txtData.Text = localsetting.Values["data"].ToString();
}
}
//sự kiện sảy ra khi trang bị đóng hoặc bị trang khác đè lên
//Ta thường lưu thông tin cấp độ trang trong hàm nay
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
localsetting.Values["data"] = txtData.Text;
}
}
}

Tiếp tục ta thiết kế XAML cho Page2 và Page3 (2 trang này giống y xì nhau) chủ yếu dùng để test mà thôi:

Vì nó giống nhau nên phần XAML tui chỉ ví dụ 1 Page 2, Page 3 bạn tự copy + paste sang:


<phone:PhoneApplicationPage
x:Class="LearnLifeCycle.Page2"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="page name 2" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="14,0,10,0">
<Button x:Name="btnPrevious" Content="Go to Previous Page" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="btnPrevious_Click"/>

</Grid>
<Button x:Name="btnNext" Content="Go to Next Page" HorizontalAlignment="Left" Margin="37,106,0,0" VerticalAlignment="Top" Click="btnNext_Click" Grid.Row="1"/>
</Grid>

</phone:PhoneApplicationPage>

Phần xử lý coding cho Page2.xaml.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace LearnLifeCycle
{
public partial class Page2 : PhoneApplicationPage
{
public Page2()
{
InitializeComponent();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
if (NavigationService.CanGoForward)
NavigationService.GoForward();
else
{
Uri newpage = new Uri("/Page3.xaml", UriKind.Relative);
NavigationService.Navigate(newpage);
}
}
}
}

Phần xử lý coding cho Page3.xaml.cs (giống page2):


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace LearnLifeCycle
{
public partial class Page3 : PhoneApplicationPage
{
public Page3()
{
InitializeComponent();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
if (NavigationService.CanGoForward)
NavigationService.GoForward();
else
{
Uri newpage = new Uri("/MainPage.xaml", UriKind.Relative);
NavigationService.Navigate(newpage);
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
}
}
}

Bây giờ Tui cần các bạn test các trường hợp sau:

1) Từ trang MainPage, nhập dữ liệu cho TextBox rồi bấm nút HOME

2) Sau đó nhấn nút Back

3) Từ MainPage nhập dữ liệu cho Textbox rồi chuyển qua trang 2

4) Từ trang 2 quay lại trang 1

5) Từ trang 2 qua trang 3

6) Từ trang 3 qua trang Mainpage.

Bài hướng dẫn kế tiếp tui sẽ trình bày về XAML và các control cơ bản trong Windows Phone 8.1,  các bạn chú ý theo dõi.

Chúc các bạn thành công

Bài 4: Đăng ký lập trình Windows Phone 8.1 trên thiết bị thật


Như ta đã biết Microsoft có hỗ trợ Emulator giúp chúng ta có thể lập trình thay thế thiết bị thật, tuy nhiên trong một số trường hợp thì ta không thể Test chính xác được trên thiết bị Emulator (ví dụ như Camera, Sensor…), vì vậy bài này Tui hướng dẫn các bạn cách đăng ký để có thể deploy phần mềm vào thiết bị thật để test một cách trực quan.

Bước 1:

- Cần chuẩn bị thiết bị thật + Dây cáp + cài đặt Driver hoàn chỉnh, thông thường khi mua điện thoại nhà cung cấp đã tích hợp sẵn do đó bạn chỉ cần cắm vào ngồi đợi 1 xí là máy sẽ cài đặt xong.

- Sau đó cắm thiết bị vào máy tính của bạn:

connect-htc-8x-to-pc

Bước 2:

Vào Start Screen bạn tìm kiếm Windows Phone Developer Registration 8.1 như hình Tui chụp ở dưới đây:

wp4_2

Bước 3:

Kích hoạt phần mềm:

wp4_3Bước 4:
Đăng ký

 

Bạn nhìn vòng tròn tròn đẹp đẹp Tui khoanh ở trên, nếu bạn chưa bao giờ đăng ký thì nó có nút Register và bạn bấm vào nút này để đăng ký, dĩ nhiên bạn cần có tài khoản Developer trước (nếu bạn  chưa biết thì vào link sau : http://clbtinhoc.dntu.edu.vn/index.php/huong-dan-dang-ky-tai-khoan-microsoft-developer-mien-phi-khong-can-visa/).

- Sau khi bấm Register: Bạn cần cung cấp đúng thông tin để đăng nhập

wp4_4Sau khi đăng ký thành công, bạn sẽ có màn hình sau (tới màn hình này là có thể sử dụng được thiết bị thật để lập trình).

wp4_5

Bạn cần chú ý là khi cắm thiết bị thật vào máy tính thì cần mở khóa màn hình, nếu không mở khóa thì bạn có thể gặp lỗi như sau:

wp4_6Chúc các bạn thành công.

Bài 3: Cách sử dụng Windows Phone Emulator 8.1


Trong bài này Tui sẽ hướng dẫn các bạn cách chạy Windows Phone Emulator cũng như cách sử dụng các công cụ và tính năng được tích hợp trong Emulator.

Windows Phone Emulator là gì? Bạn hiểu nôm na nó là một công cụ dùng để thay thế cho thiết bị thật để giúp lập trình viên có thể viết các ứng dụng và kiểm thử trên Emulator mà không cần đến thiết bị thật (Tức là nếu như ta không có tiền để mua một chú Dế thì cũng không sao, ta vẫn hoàn toàn lập trình được với Windows Phone). Tuy nhiên không phải tất cả các chức năng trong thiết bị thật đều có thể giả lập được trên Emulator, ví dụ như chức năng Camera (chỉ là các ô vuông chạy demo quanh màn hình).

Bạn có thể khởi động Windows Phone Emulator bằng các cách sau đây:

1) Khởi động từ Visual Studio

Từ Visual Studio ta chọn các Emulator cần chạy (ta có thể cập nhật thêm các Emulator bằng cách tải từ trang Microsoft cung cấp)

wp_3_3

2) Khởi động bằng command line (Không cần Visual Studio)

- Mở cửa sổ run bằng cách gõ tổ hợp phím Windows + R

- Rồi gõ lệnh sau:  “C:\Program Files (x86)\Microsoft XDE\8.1\XDE.exe” /vhd “C:\Pro
gram Files (x86)\Microsoft SDKs\Windows Phone\v8.1\Emulation\Images\Flash.vhd” /
video “720×1280″ /memsize 1024 /language 409 /creatediffdisk “%Temp%\dd.720×1280
.1024.vhd” /fastShutdown

Từ khóa “creatediffdisk” rất quan trọng, nếu ta thiếu nó thì Emulator vẫn chạy nhưng nó sẽ yêu cầu cấp quyền Admin, cái trớ trêu là nếu chạy với quyền Admin thì nó sẽ chỉnh sửa VHD image trong thư mục cài đặt, mà việc chỉnh sửa này rất nguy hiểm nó có thể không cho phép chúng ta khởi động Emulator từ Visual Studio nữa. Để biết thêm chi tiết thì bạn có thể gõ lệnh Run “XDE.exe /?“. Chú ý là nếu như bạn cài đặt với những chọn lựa mặc định của Microsoft thì bạn có thể copy + paste nguyên xi lệnh trên rồi gõ enter là hệ thống tự động kích hoạt Emulator.

wp_3_1Vì sao lại gõ đường dẫn như trên? bởi vì trong quá trình cài đặt hệ thống đã lưu trữ Emulator ở đây (do đó nếu bạn chỉ định đường dẫn khác trong quá trình cài đặt thì phải chọn đúng đường dẫn đó, còn để mặc định thì gõ như trên), ví dụ hình dưới đây là lưu trữ mặc định khi cài đặt:

wp_3_2

 

3) Sử dụng Windows Phone Power tool:

http://wptools.codeplex.com/

Cả 3 cách đều cho ra kết quả như sau:

wp_3_4 Chi tiết từng chức năng:

wp_3_5Windows Phone Emulator 8.1 có một điểm mới rất thú vị là hỗ trợ Chạm Đa Điểm giúp ta có thể lập trình đa điểm tốt  thay thế cho thiết bị thật: Khi bạn bấm vào biểu tượng Ngón Trỏ Tay thì màn hình sẽ xuất hiện 3 hình tròn cho phép chúng ta: Phóng to, thu nhỏ, xoay, quay, di chuyển, bẻ góc….

wp_3_15Windows Phone 8.1 hỗ trợ SD Card, nó được để trong Công Cụ Sử dụng Windows Phone Emulator nâng cao, bây giờ bạn bấm vào nút này để tiếp tục xem các chức năng nâng cao của Emulator (Nút cuối cùng):

wp_3_6Tab Accelerometer: Giả lập cảm biến gia tốc, bạn có thể đổi các hướng X,Y,Z tùy ý để test gia tốc bằng cách di chuyển nút hình tròn màu nghệ:

wp_3_7Hoặc bạn cũng có thể chọn những hướng chuẩn thường sử dụng bằng cách chọn mục Combobox Orientation:

wp_3_8Để chụp hình Emulator mà bạn đang thao tác, bạn vào Tab Screenshot:

wp_3_9Để cấu hình SD Card bạn vào tab SD Card:

wp_3_10Local folder: Chỉ định nơi lưu trữ

Bấm Insert SD Card để tạo SD Card hệ thống sẽ tiến hành đồng bộ, nút Insert SD Card sẽ được đổi thành “Eject SD Card”, đồng thời trong Windows Phone Emulator cũng hiển thị Message Box xác nhận:

wp_3_12Windows Phone Emulator:

wp_3_11Chọn Yes để chấp nhận và di chuyển tới màn hình Storage Sense:

wp_3_13Đồng thời bạn quan sát thư mục SD Card trong PC cũng đổi như sau:

wp_3_14Các tab khác ta sẽ đề cập tới sau khi làm các bài tập có liên quan.

Ngoài các chức năng trên ta cần biết thêm các phím tắt để thao tác vơi Windows Phone Emulator:

– Sử dung Keyboard cho Emulator:

+ Nhấn Phím Page Up/Down để cho phép tắt mở chức năng nhập thông tin từ bàn phím cho Emulator –> Tăng tốc độ.

Dưới đây là bảng chi tiết mà Microsoft cung cấp:

Computer hardware key hardware button Notes
F1 BACK Long presses work as expected.
F2 START Long presses work as expected.
F3 SEARCH
F4 Not applicable.
F5 Not applicable.
F6 CAMERA HALF A dedicated camera button that is pressed halfway.
F7 CAMERA FULL A dedicated camera button.
F8 Not applicable.
F9 VOLUME UP
F10 VOLUME DOWN
F11 Not applicable.
F12 POWER Press the F12 key twice to enable the lock screen.Long presses work as expected.
ESC BACK Long presses work as expected.
PAUSE/BREAK Toggle Keyboard Toggles the hardware keyboard.
PAGE UP Keyboard Up Enables the hardware keyboard.
PAGE DOWN Keyboard Down Disables the hardware keyboard.

Link : http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn632391.aspx

Như vậy Tui đã giới thiệu sơ lược một số chức năng trong Windows Phone Emulator, hi vọng nó sẽ giúp ích được cho bạn trong quá trình lập trình. Khi gặp các bài tập có liên quan Tui sẽ bổ sung tiếp để các bạn dễ nắm bắt.

Chúc các bạn thành công.

 

 

 

Bài 2: Cách tạo một Project Windows Phone 8.1


Ở bài 1 các bạn đã chuẩn bị đầy đủ vũ khí đạn dược cho việc chiến đấu với Windows Phone 8.1, trong bài này Tui sẽ hướng dẫn các bạn cách tạo một Project Windows Phone 8.1 như thế nào, đặc biệt phải hiểu được cấu trúc, thành phần, cách đóng gói và triển khai ứng dụng lên Emulator cũng như thiết bị thật như thế nào.

Bước 1:

- Khởi động Visual Studio Ultimate 2013, vào menu File/ chọn New/ Project (hoặc nhấn tổ hợp phím Ctrl + Shift+N) như hình dưới đây:

wp_bai2_1Bước 2:

Ở màn hình New Project ta chọn các thông số như hình dưới đây:

wp_2_1- Phần Template bên tay trái ta chọn Windows Phone Apps

- Phần danh sách loại Project ở giữa màn hình ta chọn Blank App (Windows Phone)

- Mục Name: Đặt tên cho Project, ở đây ta đặt FirstAppSample

–> Sau đó bấm nút OK để tạo một Windows Phone Project

Sau đây là cấu trúc của một Project Windows Phone:

wp_2_2Hệ thống sẽ tự động tạo ra các tập tin: App.xaml, MainPage.xaml, Package.appxmanifest…

- Toàn bộ cấu hình của ứng dụng đều nằm trong Package.appxmanifest.

- MainPage.xaml sẽ được tải đầu tiên khi ứng dụng được chạy (mặc lấy làm màn hình chính), ta cũng có thể thay thể bởi các màn hình khác.

- Assets: Chứa tập hợp các tập tin logo, icon… ta có thể kéo thả các tập tin vào đây: Hình ảnh, âm thanh…

Bây giờ ta thử kéo thả 1 Button vào MainPage :

–> Double click vào MainPage.xaml để hiển thị chi tiết các vùng trong môi trường làm việc Visual Studio:

wp_2_3Ở trên Tui đánh dấu từ 1–>5:

 Vùng số 1: Hiển thị các control để kéo thả vào vùng số 2, nếu như Vùng số 1 không xuất hiện thì bạn vào Menu View/ Toolbox (hoặc nhấn tổ hợp phím Ctrl +Alt+ X)

Vùng số 2: Nơi hiển thị Giao diện Điện Thoại cho phép ta thiết kế ứng dụng

Vùng số 3: Nơi cho phép ta dùng XAML code để thiết kế giao diện, chú ý rằng ở Vùng số 1 mỗi lần ta kéo thả control vào vùng số 2 thì vùng số 3 tự động cập nhật các XAML code (tự phát sinh). Có nghĩa là ta có thể thiết kế giao diện cho vùng Số 2 bằng cách kéo thả ở vùng số 1 vào hoặc gõ bằng XAML code trong vùng số 3.

Vùng số 4: Cấu trúc thư mục của ứng dụng

Vùng số 5: Cấu hình Properties, Event… cho các đối tượng trong ứng dụng. Ví dụ khi kéo Button ra tui đặt tên cho Button này là btnClickMe, thì trong mục Properties có ô Name ta gõ vào btnClickMe. Nội dung hiển thị cho Button này là “Click Me!” thì ta gõ vào ô Content.

Để gán sự kiện cho Button ta Double click vào Button đó thì nó tự động phát sinh sự kiện hoặc ta vào tab Event để thiết lập sự kiện cho control:

wp_2_5Ta xem sự kiện phát sinh, ở đây khi chạm vào Button ta sẽ đổi thành màu Vàng:

wp_2_4Bạn quan sát là đối với một màn hình thì hệ thống sẽ có tập tin: .xaml và .xaml.cs . Ví dụ MainPage.xaml là tập tin để thiết kế giao diện, MainPage.xaml.cs là nơi để coding chúng được tách biệt ra làm 2 tập tin độc lập nhưng cùng làm việc cho lớp MainPage.

Bây giờ ta có thể nhấn phím F5 để chạy ứng dụng, chú ý rằng mặc định sẽ chạy trên Emulator, ta có thể lựa chọn chạy trên thiết bị thật cũng như chọn các loại Emulator khác nhau bằng cách chọn theo mục như hình dưới đây:

wp_2_6Để chạy trên máy thật ta chọn Device

Để chạy máy ảo Emulator thì tùy ta chọn mục Emulator, ứng với mỗi loại khác nhau thì Emulator hiển thị khác nhau.

Kết quả sau khi ta thực hiện chương trình trên:

wp_2_7Khác so với Windows Phone 8.0 (.xap), Windows Phone 8.1 biên dịch ra tập tin .exe wp_2_8Cách sử dụng Package.appxmanifest trong Project:

Tập tin này cho phép ta cấu hình các đặc tính của ứng dụng: Camera, Sensor, Contact, Music Library…

Ta double click vào tập tin này nó sẽ hiển thị ra với nhiều Tab: Capabilities, Application, Declarations, Content URIs, Visual Assets, Packaging, Requirements. Mỗi tab có những chức năng cấu hình khác nhau (ta cần hiểu rõ để cấu hình ứng dụng cho tốt):

wp_2_9Tab Application: Dùng để thiết lập các thuộc tính và mô tả cho ứng dụng

Tab Visual Assets: Dùng để cấu hình hỗ trợ các độ phân giải khác nhau, cùng các thiết lập Logo, Splash Screen….

Tab Requirements:  Tab này cho phép ta yêu cầu cấu hình phần cứng của thiết bị khi cài đặt ứng dụng, ví dụ như yêu cầu phần cứng phải có Sensor, NFC, Camera… nếu không có thì không cho phép cài ứng dụng.

Tab Capabilities: Thiết lập các đặc tính cho phép ứng dụng có thể sử dụng các tính năng trong thiết bị, ví dụ như: Cho phép sử dụng Contacts, Microphone, SD Card, Webcam….

Tab Packaging: Thiết lập thông số cấu hình phiên bản, package name và display name…

Tab Declarations: Để thiết lập các khai báo cũng như thuộc tính cho chúng

Tab Content URIs: Dùng để khai báo các HTTPS URI để sử dụng window.external.notify để gửi sự kiện ScriptNotify tới ứng dụng.

Chú ý:  Để thiết lập trang mặc định khi ứng dụng được khởi động thì ta sửa hàm sau trong lớp App.xaml.cs:


protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
          ...
                if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
         ...
        }

Thành:


protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
          ...
                if (!rootFrame.Navigate(typeof(SecondPage), e.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
         ...
        }

Muốn chạy trang nào mặc định thì ta sửa như trên, ở bên trên Tui ghi là Secondpage, bạn có thể chỉ định bất kỳ trang nào vào đây.

Bài kế tiếp Tui sẽ hướng dẫn các bạn cách sử dụng Windows Phone 8.1 Emulator, việc sử dụng Emulator thành thạo là rất quan trọng nó giúp lập trình viên tăng tốc độ xử lý coding đặc biệt nó dường như có thể thay thế cho thiết bị thật.

Chúc các bạn thành công.

Bài 1: Các bước chuẩn bị lập trình với Windows Phone 8.1


Xin chào các bạn Sinh viên đang tham gia học lập trình Windows Phone!

Để giúp các bạn có thể tự học ở nhà khi không tham dự được lớp học cũng như bổ sung thêm một số kỹ năng lập trình nâng cao liên quan tới Windows Phone. Vì vậy Tui sẽ tiến hành biên soạn Step by Step từ dễ đến khó và đính kèm source code mẫu để các bạn có thể dễ dàng học tập, hàng tuần Tui sẽ cố gắng publish một vài bài theo thứ tự.

Ở bài tập đầu tiên này Tui sẽ trình bày sơ lược cách thức chuẩn bị lập trình với Windows Phone 8.1, cụ thể:

- Yêu cầu tối thiểu cấu hình máy

- Kiểm tra Tính năng Ảo Hóa

- Kiểm tra tính năng SLAT

- Kích hoạt Hyper-V

- Cách cài đặt Visual Studio Ultimate 2013

- Cách cài đặt Visual Studio Ultimate 2013 Update 2

Sau đây là nội dung chi tiết cho các phần trên:

 1) Yêu cầu tối thiểu cấu hình máy:

Kiểm tra Bios có các đặc tính dưới đây được hỗ trợ hay không:

  • Hardware-assisted virtualization.
  • Second Level Address Translation (SLAT).
  • Hardware-based Data Execution Prevention (DEP).

RAM:

Tối thiểu 4GB

OS:

Windows 8.1 Pro 64 bit trở lên

Tui chụp hình cấu hình hệ thống máy Tui đang sử dụng dưới đây:

wp_systeminfor_12) Kiểm tra Ảo hóa, SLAT, DEP:

Microsoft hỗ trợ Tool để kiểm tra 3 đặc tính bắt buộc để lập trình với Windows Phone 8/8.1 : http://technet.microsoft.com/en-us/sysinternals/cc835722

Ta tải file nén Coreinfo.zip ở link trên về rồi tiến hành chạy cmd với Administrator để kiểm tra như sau:

wp_coreinfor_1Ở hình trên bạn chỉ cần gõ lệnh: Coreinfo.exe -v thì hệ thống sẽ hiển thị các thông tin như bên dưới, ở trên Tui có gạch màu vàng 3 chỗ, nếu bạn cũng có các thông tin đó thì coi như là Máy Tính của bạn có thể lập trình được với Windows Phone 8/8.1

Thông thường khi bạn cài đặt máy thì chức năng ảo hóa chưa được kích hoạt, bạn cần vào Bios để kích hoạt nó lên (enable), Tùy vào hãng sản xuất khác nhau mà có cách kích hoạt khác nhau (bạn cố gắng Mò trong Bios của bạn).

3) Kích hoạt Hyper-V

Ta cần kích hoạt Hyper – V để tiến hành lập trình với Emulator, nếu máy tính của bạn chưa được kích hoạt thì khi chạy bạn sẽ nhận được lỗi tương tự như sau:

wp_hyperv1_1Hay nếu như đã kích hoạt nhưng không chạy trong chế độ Hyper-V Administrators group thì ta cũng nhận được lỗi:

wp_hyperv2_1Vậy làm sao để kích hoạt Hyper-V?

Bước 1:

Chọn Programs and Features trong Control Panel như hình dưới đây:

wp_controlpanel_1_1Bước 2:

Chọn Turn Windows Features On or Off

wp_controlpanel_2_1Màn hình Windows Features sẽ hiển thị ra như dưới đây:

Bước 3:

- Tick chọn Hyper-V trong màn hình Windows Features:

wp_controlpanel_3_1Sau khi chọn các Tick giống như hình trên, ta bấm OK và chờ cho hệ thống thiết lập xong.

 Bước 4:

Kiểm tra Hyper-V Manager

Sau khi hoàn thành bước 3, hệ thống sẽ tạo Hyper-V để kiểm tra ta tìm từ khóa Hyper-V Manager như hình dưới đây:

wp_hyperv3_1Bấm chọn Hyper-V Manager để hiển thị chương trình quản lý Hyper – V như dưới đây:

wp_hyperv4_1ở màn hình trên Ta có thể cấu hình nhiều thông số khác nhau, có thể Start, Stop dịch vụ… Như vậy khi nào chạy Emulator mà báo lỗi gì đó liên quan tới Hyper-V thì bạn có thể vào đây để cấu hình lại.

 4) Cài đặt Visual Studio Ultimate 2013Visual Studio Ultimate 2013 Update 2

Vì Windows Phone 8.1 SDK nằm trong Visual Studio Ultimate 2013 Update 2 nên sau khi cài đặt Visual Studio Ultimate 2013 thì bắt buộc ta phải cài đặt bản Update 2.

Nếu ngay từ đầu bạn cài đặt bản Visual Studio Ultimate 2013 Update 2 thì hệ thống có thể không cho phép và ngay từ đầu sẽ báo lỗi như hình dưới đây:

wp_visualupdate2_1Có nhiều cách giải quyết vấn đề trên, ở đây Tui đưa ra một cách như sau:

Bước 1: Vẫn phải cài bản Visual Studio Ultimate 2013 trước (chú ý là không phải Update 1 cũng không phải Update 2)

Ở bản này đã đính kèm sẵn Windows Phone 8.0 SDK bạn cũng tiến hành checked nó để cài luôn

Bước 2: Sau khi cài đặt thành công Visual Studio Ultimate 2013, thì bạn tiến hành cài đặt bản Visual Studio Ultimate 2013 Update 2 như vậy là sẽ thành công. Và bạn sẽ có bản Windows Phone 8.1 SDK.

Như vậy tới đây là bạn có thể tiến hành lập trình Windows Phone 8.1 .

Bài kế tiếp Tui sẽ hướng dẫn các bạn cách tạo 1 Project Windows Phone 8.1 như thế nào, kiến trúc, thành phần cũng như cách chạy trên Emulator và thiết bị thật như thế nào, các bạn chú ý theo dõi.

Chúc các bạn thành công.

 

Bài 48: Cách sử dụng Facebook SDK trong Android


Sau đây Tui sẽ trình bày các tính năng của Facebook SDK trong Android, các bạn có thể tự tìm hiểu trên internet nó có vô số ví dụ mẫu.

Tui sẽ trình bày theo cách của tui (cách của Dr Thanh), nếu các bạn hứng thú thì có thể theo dõi để viết một số App liên quan tới Facebook, vì hiện nay mạng xã hội nói chung và Facebook nói riêng nó làm thay đổi mọi hành vi của con người đặc biệt là đối với giới trẻ: ăn facebook, uống facebook, ngủ facebook, vui facebook, buồn facebook, không vui không buồn cũng facebook, cãi lộn cũng facebook, dìm hàng cũng facebook…. túm lại tình yêu đích thực của giới trẻ theo tui hình như là facebook.

- Các bạn tải Facebook SDK tại đây: https://developers.facebook.com/docs/android/

- Bạn phải biết cách đưa nó vào Eclipse để sử dụng, đây là hướng dẫn step by step bằng tiếng anh: https://developers.facebook.com/docs/android/getting-started/

- Tui sẽ trình bày lại các ví dụ mà hãng Facebook cung cấp cho các bạn hiểu cốt lõi của nó trước, sau đó Tui sẽ đưa ra các bài nâng cao để các bạn luyện công!.

Ở bài này Tui trình bày lại ví dụ hiển thị Picture Profile theo Facebook ID có giao diện của họ cung cấp như sau:

3fb0

- Ở màn hình trên, Tui sửa lại 4 Facebook ID theo nhãn: Duy Thanh, Xuân Diệu vợ Tui, Tích Đạt và Hoàng Phong là 2 người bạn.

- Hình  I’m So Cool với bộ mặt lông lá lổm chổm là của ông Hoàng Phong mà chương trình tự động lấy từ Facebook về dựa vào ID của ông Phong mà tui nhét vào Tag của Button “Hoàng Phong”.

- Các bạn tải SDK về và cố gắng đưa vào Eclipse thử xem được không, Tui nghĩ các bạn sẽ gặp một số lỗi nhưng hãy cố gắng sửa sao cho nó chạy được SDK là OK.

- Tui sẽ tiếp tục trình bày về ví dụ này cũng như Graph API để có thể lấy được danh sách bạn bè, tin nhắn…

- Các bạn chú ý theo dõi!

Bài 47: Xử lý tin nhắn SMS bằng BroadCastReceiver


Để hỗ trợ cho dự án nêu trong bài tập số 43(Đăng Ký Học Phần Bằng SMS cho các Trường Đại Học) Tui đã cung cấp hàng loạt các bài 40, 41, 44, 45, 46, 47 các bạn cần đọc kỹ lại những bài tập này trước khi bắt tay vào làm bài tập 43.

Ở bài tập 47 này, Tui muốn hướng dẫn các bạn cách sử dụng BroadCastReceiver được đăng ký chạy background trong Android Manifest, để nó có thể tự động “bắt” được tin nhắn SMS bất kỳ nào nhắn tới cho dù chúng ta không mở ứng dụng.

- Tui muốn ghi chú các bạn là:

1) Để nhận biết được đâu là Tin Nhắn đăng ký học phần thì bắt buộc các bạn phải có một CÚ PHÁP gửi tin nhắn riêng, giống như hàng ngày trên TIVI đều có hướng dẫn cú pháp đăng ký hay bỏ phiếu cho ai đó. Tương tự như vậy để nhận biết được tin nhắn đăng ký học phần thì hệ thống Website trường đại học cũng phải cung cấp CÚ PHÁP đăng ký 1 học phần như thế nào đúng không?

3) Khi 1 tin nhắn gửi tới mà ta phân tích được nó chính là tin nhắn CÚ PHÁP đăng ký học phần thì mới tiến hành xử lý đăng ký, việc xử lý đăng ký là vô cùng phức tạp vì đòi hỏi bạn phải hiểu biết cặn kẽ về quy trình xử lý học vụ, đối với trường hợp ở bài tập 43 thì bạn có thể làm ví dụ sơ sơ cũng được, nhưng theo TUI muốn làm thực tế và bán được lại cho các trường đại học muốn áp dụng công nghệ thì bạn phải đến trực tiếp trường học, liên hệ (tốt nhất là có mối quan hệ sâu sắc) để hiểu được quy trình xử lý học vụ, như vậy may ra dự án của bạn mới áp dựng thực tế còn không chỉ là làm sương sương chơi cho vui.

4) Với bài tập 47 này thì Tui chỉ làm 1 phần nhỏ: Nhận 1 tin nhắn theo cú pháp, trả lời tin nhắn có sự kiểm tra là tin nhắn đã được gửi thành công hay thất bại (dùng PendingIntent).

Công việc còn lại của bạn là sau khi nhận được tin nhắn theo cú pháp rồi, tiến hành phân tích  đưa thông tin lên  Server thông qua Webservice, kiểm tra kết quả trả về của Webservice, rồi trả lời SMS ngược lại cho người đăng ký–>có thể tự làm bài 43.

Tui có thể phác thảo mô hình phù hợp để các bạn test hệ thống này dễ dàng như sau:

3h47_0

- Dựa vào mô hình trên thì bạn có thể kiểm tra hệ thống như sau:

+ Bạn có thể biến máy tính cá nhân của bạn làm máy SERVER, CSDL + webservice được cài đặt tại máy Server này.

+ Bạn sử dụng 2 điện thoại: 1 điện thoại cài đặt phần mềm xử lý tin nhắn (gọi là Điện thoại chủ), 1 điện thoại bạn mượn đại của đứa bạn thân nhắn tin theo cú pháp vào điện thoại chủ đó. Điện thoại chủ có nhiệm vụ bắt tin nhắn và xử lý rồi gửi lên PC Server (hoặc dùng máy ảo nếu như bạn không có máy thật để test, nhưng cố gắng dùng máy thật).

- Trước khi vào ứng dụng thì tui nói CÚ PHÁP tin nhắn Tui dùng trong bài tập này để đăng ký học phần như sau:

Cú pháp:  DRTHANH MSSV MMH HK

Giải thích cú pháp:

DRTHANH là keyword đầu tiên của tin nhắn

MSSV là mã số sinh viên

MMH là mã môn học

HK là học kỳ

VÍ DỤ, nếu sinh viên gửi tin nhắn “DRTHANH 113114115 ANDROID 9″
Thì mã sinh viên =113114115
Mã môn học: ANDROID
Học kỳ 9

- Khi tin nhắn gửi tới thì ta phải phân tích nội dung tin nhắn để tiến hành xử lý cho phù hợp.

- Bạn tạo Project đơn giản như hình Tui chụp dưới đây:

3h47_1

- Bạn chú ý là thư viện KSOAP để tương tác với Webservice là bạn tự làm, Tui chủ ý không làm phần này để bạn tự tổng hợp kiến thức đưa vào đây như vậy thì mới nâng cao được kỹ năng lập trình cũng như tư duy logic cho bạn.

- Tui chỉ tiến hành làm phần BroadCastReceiver, dĩ nhiên trong này Tui có để sẵn 1 hàm Trống để bạn điền coding cập nhật vào cho dễ dàng hơn.

- Chương trình này không liên quan gì tới giao diện, vì Tui đăng ký BroadCastReceiver trong Manifest để hệ thống tự động nhận, xử lý và gửi tin nhắn (cho dù không mở ứng dụng), Nên giao diện bạn thích làm kiểu gì cũng được (tốt nhất là đừng quan tâm).

- Tui nói phần Manifest, bạn cấu hình như dưới đây:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="tranduythanh.com"
 android:versionCode="1"
 android:versionName="1.0" >
 <uses-sdk
 android:minSdkVersion="9"
 android:targetSdkVersion="18" />
 <uses-permission android:name="android.permission.SEND_SMS" />
 <uses-permission android:name="android.permission.RECEIVE_SMS" />
 <uses-permission android:name="android.permission.WRITE_SMS" />
 <uses-permission android:name="android.permission.READ_SMS" />

<application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >
 <activity
 android:name="tranduythanh.com.MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>

<receiver android:name="MyBroadCast" >
 <intent-filter>
 <action android:name="android.provider.Telephony.SMS_RECEIVED" />
 </intent-filter>
 </receiver>
 </application>

</manifest>

- Dòng lệnh 9 ->12 là đăng ký permission cho việc Nhận tin nhắn, gửi tin nhắn, ghi tin nhắn, đọc tin nhắn.

- Dòng lệnh 29- 33 là đăng ký BroadCastReceiver trong Manifest, giúp chương trình hoạt động như service chạy nền.

- Xử lý coding MyBroadCast:


package tranduythanh.com;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.widget.Toast;

public class MyBroadCast extends BroadcastReceiver {

// All available column names in SMS table
 // [_id, thread_id, address,
 // person, date, protocol, read,
 // status, type, reply_path_present,
 // subject, body, service_center,
 // locked, error_code, seen]
 public static final String SMS_EXTRA_NAME = "pdus";
 public static final String SMS_URI = "content://sms";

public static final String ADDRESS = "address";
 public static final String PERSON = "person";
 public static final String DATE = "date";
 public static final String READ = "read";
 public static final String STATUS = "status";
 public static final String TYPE = "type";
 public static final String BODY = "body";
 public static final String SEEN = "seen";

public static final int MESSAGE_TYPE_INBOX = 1;
 public static final int MESSAGE_TYPE_SENT = 2;

public static final int MESSAGE_IS_NOT_READ = 0;
 public static final int MESSAGE_IS_READ = 1;

public static final int MESSAGE_IS_NOT_SEEN = 0;
 public static final int MESSAGE_IS_SEEN = 1;
 private Context context=null;
 @Override
 public void onReceive(Context context, Intent intent) {
 this.context=context;
 processSMS(intent);
 }
 public void processSMS(Intent intent)
 {
 // Get the SMS map from Intent
 Bundle extras = intent.getExtras();

String messages = "";

if ( extras != null )
 {
 // Get received SMS array
 Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
 for ( int i = 0; i < smsExtra.length; ++i )
 {
 SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
 String body = sms.getMessageBody().toString();
 String address = sms.getOriginatingAddress();

messages += "SMS from " + address + " :\n";
 messages += body + "\n";
 //gọi hàm xử lý nội dung và gửi kết quả trả về
 doSending(address,body);
 }
 // Display SMS message từ các điện thoại khác gửi tới
 Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
 }
 }
 public void doSending(String phoneNumber,String body)
 {
 try
 {
 //đặng ký Pending Intent để kiểm soát kết quả gửi tin nhắn trả về thành công hay không?
 final SmsManager sms = SmsManager.getDefault();
 Intent msgSent = new Intent("ACTION_MSG_SENT");
 final PendingIntent pendingMsgSent =
 PendingIntent.getBroadcast(context, 0, msgSent, 0);
 context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
 public void onReceive(Context context, Intent intent) {
 int result = getResultCode();
 String msg="Gửi tin nhắn trả lời thành công";
 if (result != Activity.RESULT_OK) {
 msg="Gửi tin nhắn trả lời thất bại";
 }
 Toast.makeText(context, msg,
 Toast.LENGTH_LONG).show();
 }
 }, new IntentFilter("ACTION_MSG_SENT"));
 //nếu đúng là cú pháp đăng ký học phần.
 if(isSyntaxForRegisterCourse(body))
 {
 processRegisterCourse(body);
 sms.sendTextMessage(phoneNumber, null, "Hệ thống đã nhận được tin đăng ký học phần của bạn! chờ giây lát!",
 pendingMsgSent, null);
 }
 else
 {
 //chỉ là tin nhắn thường
 //tự động trả lời -- coi chừng tốn tiền khi dùng máy thật nhá
 sms.sendTextMessage(phoneNumber, null, "DrThanh tự động trả lời bạn! Củm ơn!",
 pendingMsgSent, null);
 }

 }
 catch(Exception ex)
 {
 Toast.makeText(context, ex.getMessage(),Toast.LENGTH_LONG).show();
 }
 }
 //Giả sử cú pháp bạn quy định là:
 //DRTHANH MSSV MMH HK
 //DRTHANH là keyword đầu tiên của tin nhắn
 //MSSV là mã số sinh viên
 //MMH là mã môn học
 //HK là học kỳ

 //VÍ DỤ body= DRTHANH 113114115 ANDROID 9
 //Thì mã sinh viên =113114115
 //mã môn học: ANDROID
 //học kỳ 9
 public boolean isSyntaxForRegisterCourse(String body)
 {
 String arr[]=body.split(" ");
 if(arr.length!=4)
 return false;
 if(!arr[0].equalsIgnoreCase("DRTHANH"))
 return false;
 return true;
 }
 /**
 * Các bạn xử lý đăng ký học phần tại đây
 * Phân tích và gửi dữ liệu lên Server thông qua Webservice
 * Vậy trên Server bạn viết 1 Webservice xử lý đăng ký học phần là OKÊ
 * @param body
 */
 public void processRegisterCourse(String body)
 {
 //tự viết lệnh chỗ này
 //xem lại các bài tập mà Tui hướng dẫn trước đó để làm
 //chúc bạn may mắn.
 }
}

- Bạn kiểm tra dòng lệnh 13, ta tạo 1 lớp tên là MyBroadCast kế thừa từ BroadCastReceiver.

- Dòng lệnh 43, onReceive dùng để tự động bắt tin nhắn khi có bất kỳ tin nhắn nào gửi tới. Tại một thời điểm thì có thể có nhiều tin nhắn gửi tới cùng 1 lúc nên ta dùng vòng lặp để lặp qua toàn bộ tin nhắn và xử lý.

- Dòng lệnh 73 là hàm doSending, ở đây Tui viết hàm này chủ ý xử lý tin nhắn gửi tới có đúng cú pháp đăng ký hay không, tùy loại tin nhắn mà ta xử lý khác nhau.

- Dòng lệnh 140, hàm processRegisterCourse, Tui để trông để bạn tự viết coding vào đây, sử dụng KSOAP API để gửi thông tin lên cho Webservice xử lý học vụ.

- Bây giờ bạn có thể test thử: Cài phần mềm này vào 1 điện thoại, lấy 1 điện thoại khác nhắn tin theo đúng cú pháp vào điện thoại cài phần mềm, thì sẽ có kết quả như mong muốn.

- Tui đã test thử trên các thiết bị điện thoại thật và đã thành công, bạn cũng thử cài đặt vào để Test cho hiệu quả.

- Bạn có thể tải source code mẫu ở đây: http://www.mediafire.com/download/k12pl9ccqu85dgn/LearnBroadCastReceiver_SMS_With_Manifest.rar

- Bài này có rất nhiều ứng dụng thực tế để kiếm tiền, và bạn cũng chú ý là rất nhiều phần mềm trên Google Play tải về có chức năng tự động gửi tin nhắn nên bạn phải cẩn thận kẻo bị trừ hết ráo không còn xu nào, khi cài đặt thì làm ơn đọc kỹ trước khi bấm Next hay OK. Thường thì nếu phần mềm có dùng SMS thì khi cài vào máy thật nó sẽ Cảnh báo, ta phải đọc kỹ, hãy bỏ thói quen tỏ vẻ nguy hiểm là không thèm đọc cứ bấm Next, OK… rất nguy hiểm.

- Chúc các bạn thành công.

Bài 46: Sử dụng .Net Webservice trong Android


Để làm được bài 46 thì các bạn nên xem qua trước bài tập 44 và 45.

Trong bài tập 46 này Tui muốn trình bày 4 ví dụ về cách tương tác từ Android tới .net web service thông qua thư viện KSOAP API.

Các ví dụ này lần lượt sẽ là:

1) Cách lấy dữ liệu Primitive Data từ .net webservice xuống Android

2) Cách lấy dữ liệu Complex Data từ .net webservice xuống Android

3) Cách truyền Parameter primitive data từ Android tới .net web service

4) Cách truyền Object data từ Android tới .net web service

Thư viện KSOAP  API các bạn tải ở đây (tạm thời tự nghiên cứu trước): http://www.mediafire.com/download/kmznar1je4702ga/ksoap2-android-assembly-2.6.0-jar-with-dependencies.jar

Tui sẽ tranh thủ đưa 4 ví dụ trên để các bạn có thể kịp làm bài tập 43.

——————————————————————————

Tất cả 4 ví dụ này Tui sẽ sử dụng Service Description của http://testdrthanh.somee.com/mywebservice.asmx?WSDL ở bài tập trước. Khi bạn mở với Service description thì nó cung cấp cho bạn đầy đủ thông tin như hình Tui chụp dưới đây:

2h46_0

NameSpace và tên hàm là rất quan trọng để dựa vào nó ta truy xuất dữ liệu, nên sai namespace hay method thì chắc chắn không thể truy suất.

Sau đây tui hướng dẫn các bạn những ví dụ ở trên

Các bài phải :

<uses-permission android:name=”android.permission.INTERNET” />

1) Cách lấy dữ liệu Primitive Data từ .net webservice xuống Android

- Bạn tạo một Project Android giống như hình Tui chụp dưới này:

2h46_1

Bạn chú ý là Tui đánh thứ tự từ 1, 2, 3, 4 là có ý đồ kỹ thuật. Bạn phải sắp xếp như vậy thì chương trình mới sử dụng đúng thư viện và có thể truy suất webservice, nếu đặt sai có thể nó báo lỗi không thể thực thi ứng dụng.

Mặc định khi bạn tạo Project thì nó sẽ không đúng thứ tự như vậy đâu, bạn phải tự làm lại thứ tự, cách đổi thứ tự như thế nào Tui sẽ nói rõ cho bạn.

Tiếp tới là bạn phải tham chiếu tới thự Viện KSOAP API mà tui khoanh màu đỏ, bạn lưu nó ở đâu thì bạn tham chiếu tới cho đúng, hoặc bạn có thể nhét nó vào thư viện libs. (bấm chuột phải vào Project / chọn Build Path/ chọn Add External Archives –> chọn đúng thư viện KSOAP API để add vào ứng dụng)

- Cách đổi thứ tự tham chiếu như sau:

Bấm chuột phải vào Project của bạn/ chọn Build Path/Configure build path…:

2h46_2

Cửa sổ mới hiển thị lên/chọn tab Order and export:

2h46_3

Ta sắp xếp như màn hình trên, để di chuyển thì dùng các nút : Up,down, top, bottom.

Bạn chú ý là phải đảm bảo rằng tất cả các mục trong này được CHECKED rồi mới bấm nút OK.

- Sau đây là giao diện chính (rất đơn giản) của project này như sau:

2h46_4- Nút “Get Catalog count” sẽ triệu gọi Service và trả về có bao nhiêu Danh mục trong Cơ sở dữ liệu.

- Cấu trúc XML của giao diện:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >

<TextView
 android:id="@+id/textView1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Number Of Catalog:" />

<TextView
 android:id="@+id/txtcount"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#008040"
 android:gravity="center"
 android:textColor="#FFFFFF"
 android:textSize="30sp" />

<Button
 android:id="@+id/btncount"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Get Catalog Count" />

</LinearLayout>

- Ta tiến hành xử lý coding trong MainActivity.java như sau:


package tranduythanh.com;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
 TextView txtcount;
 Button btncount;
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 //thiết lập Permit để kết nối internet
 StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);

 txtcount=(TextView) findViewById(R.id.txtcount);
 btncount=(Button) findViewById(R.id.btncount);
 btncount.setOnClickListener(new
 View.OnClickListener() {
 public void onClick(View arg0) {
 doCount();
 }
 });
 }
 public void doCount(){
 try{
 //khai báo namespace trong Webservice
 final String NAMESPACE="http://tranduythanh.com/";
 //hàm cần truy suất
 final String METHOD_NAME="CountCatalog";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;
 //service description
 final String URL="http://testdrthanh.somee.com/mywebservice.asmx?WSDL";
 //khai báo đối tượng SoapOBject
 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
 //thiết lập version
 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 //thiết lập output
 envelope.setOutputSoapObject(request);
 //tạo đối tượng HttpTransportSE
 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 //tiến hành triệu gọi Service
 androidHttpTransport.call(SOAP_ACTION, envelope);
 //lấy kết quả trả về SoapPrimitive, vì hàm CountCatalog chỉ trả về kiểu int (primitive data)
 SoapPrimitive response=(SoapPrimitive) envelope.getResponse();
 //hiển thị kết quả lên giao diện
 txtcount.setText(response.toString());
 }
 catch(Exception e) {
 e.printStackTrace();
 }
 }
}//end MainActivity

- Bạn quan sát dòng lệnh:


StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);

Dòng lệnh trên là cho phép ứng dụng kết nối tới internet, nhưng chú ý cách làm này là không TỐT, phải sửa lại. Từ Android 4.0 nó yêu cầu khi kết nối internet phải viết trong Tiểu Trình (dùng đa tiến trình, các bạn xem lại các ví dụ trước). Còn viết như bên trên TUI viết thì rất dở, nó làm Đơ Ứng Dụng vì phải mất Time Request, chỉ là giải pháp tình huống để các bạn dễ hiểu thôi.

Bạn nên xóa dòng lệnh bên trên đi, đưa hàm doCount() vào một tiểu trình (bạn dùng Handler class hoặc AsyncTask class), cách làm đa tiến trình Tui đã hướng dẫn rất kỹ lưỡng ở những bài trước, bài này các bạn tự làm (nếu không làm được thì chưa đạt).

Bạn tải source code ở đây (nhớ khi down về thì đổi lại tham chiếu tới thư viện KSOAP), bạn nên nhét nó vào thư mục Libs để chép tới nơi khác không phải tham chiếu lại:

http://www.mediafire.com/download/wo4211x3ra3x7q3/LearnWebservice_ForPrimitiveData.rar

Bạn phải chú ý làm nhiều lần để cho hiểu rõ vấn đề.

2) Cách lấy dữ liệu Complex Data từ .net webservice xuống Android

- Ở phần 1 Bạn đã biết cách truy suất webservice và trả về dữ liệu Primivite data, trong bài này Tui hướng dẫn các bạn lấy dữ liệu về dạng Complex Data.

- Cách cấu hình tham chiếu thư viện, đổi thứ tự tham chiếu … thì ở mục 1 tui đã nói, mục này Tui đi thẳng vào ứng dụng:

- Tui muốn tạo 1 Ứng dụng cho phép triệu gọi danh sách Danh Mục Sản phẩm từ webservice với giao diện vô cùng đơn giản như sau (bạn tạo ứng dụng tên là LearnWebservice_complex_data):

2h46_6- Ứng dụng trên sẽ triệu gọi hàm : getListCatalog.

- Nó khác biệt là nó trả về danh sách đối tượng Danh Mục, làm thế nào để ta lấy được danh sách đối tượng nafy???

- Sau đây là XML Layout của ứng dụng:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >

<Button
 android:id="@+id/btnlistcatalog"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Get List Catalog" />

<ListView
 android:id="@+id/lvcatalog"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>

</LinearLayout>

- Source code Xử lý trong MainActivity như sau:


package tranduythanh.com;

import java.util.ArrayList;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class MainActivity extends Activity {
 Button btngetlist;
 ListView lvcatalog;
 final String URL="http://testdrthanh.somee.com/mywebservice.asmx?WSDL";
 ArrayList<String> arrCate=new ArrayList<String>();
 ArrayAdapter<String>adapter=null;
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);
 lvcatalog=(ListView) findViewById(R.id.lvcatalog);
 btngetlist=(Button) findViewById(R.id.btnlistcatalog);
 btngetlist.setOnClickListener(new View.OnClickListener() {
 public void onClick(View arg0)
 {doGetList();}
 });
 adapter=new ArrayAdapter<String>
 (this, android.R.layout.simple_list_item_1, arrCate);
 lvcatalog.setAdapter(adapter);
 }
 public void doGetList() {
 try{final String NAMESPACE="http://tranduythanh.com/";
 final String METHOD_NAME="getListCatalog";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;
 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 envelope.setOutputSoapObject(request);
 //Nếu truyền số thực trên mạng bắt buộc phải đăng ký MarshalFloat
 //không có nó thì bị báo lỗi
 MarshalFloat marshal=new MarshalFloat();
 marshal.register(envelope);

 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 androidHttpTransport.call(SOAP_ACTION, envelope);
 //Get Array Catalog into soapArray
 SoapObject soapArray=(SoapObject) envelope.getResponse();
 arrCate.clear();
 //soapArray.getPropertyCount() return number of
 //element in soapArray
 //vòng lặp duyệt qua từng dòng dữ liệu
 for(int i=0; i<soapArray.getPropertyCount(); i++)
 {
 //(SoapObject) soapArray.getProperty(i) get item at position i
 SoapObject soapItem =(SoapObject) soapArray.getProperty(i);
 //soapItem.getProperty("CateId") get value of CateId property
 //phải mapp đúng tên cột:
 String cateId=soapItem.getProperty("CateId").toString();
 String cateName=soapItem.getProperty("CateName").toString();
 //đẩy vào array
 arrCate.add(cateId+" - "+cateName);
 }
 //xác nhận cập nhật giao diện
 adapter.notifyDataSetChanged();
 }
 catch(Exception e){}}
}

Như vậy bạn chú ý có sự khác biệt trong Vòng lặp duyệt để lấy thông tin từng dòng đối tượng, bạn chú ý ngẫm nghĩ để tự áp dụng cho các bài toán khác (lấy danh sách sản phẩm, lấy danh sách sản phẩm theo danh mục ….)

Bạn tải source code mẫu ở đây: http://www.mediafire.com/download/r2i7sayask0m9xl/LearnWebservice_complex_data.rar

Chú ý phải làm lại nhiều lần, nhất là Tui đảm bảo các bạn còn Quáng Gà với vòng lặp lấy dữ liệu ở trên.

3) Cách truyền Parameter primitive data từ Android tới .net web service

- Hai phần trên các bạn đã biết cách lấy dữ liệu primitive data và complex data từ Server về client, phần 3 này các bạn sẽ được học cách thức truyền dữ liệu từ client lên server thông qua Webservice như thế nào.

- Giao diện của bài tập 3 như sau:

2h46_7

- Mô tả sương sương như sau: Màn hình chính cho phép hiển thị danh mục, mỗi lần nhấn vào danh mục nào đó thì hiển thị danh sách sản phẩm của danh mục này. Ở đây ta dùng hàm getListProductByCatalogId của webservice để hiển thị danh sách sản phẩm theo danh mục.

-Bạn tạo Project như dưới đây:

2h46_8

- Vậy chương trình có 2 Activity, một số class: Product, Cate…

- Layout “activity_main.xml”:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >

<Button
 android:id="@+id/btnlistcatalog"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Get List Catalog" />

<ListView
 android:id="@+id/lvcatalog"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>

</LinearLayout>

- Layout “activity_list_product_by_catalog.xml”:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".ListProductByCatalogActivity" >
 <ListView
 android:id="@+id/lvproduct"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>

</LinearLayout>

- Lớp Product:


package tranduythanh.com;

public class Product {
 private String productId;
 private String productName;
 private int quantity;
 private double unitPrice;
 private double totalMoney;
 public String getProductId() {
 return productId;
 }
 public void setProductId(String productId) {
 this.productId = productId;
 }
 public String getProductName() {
 return productName;
 }
 public void setProductName(String productName) {
 this.productName = productName;
 }
 public int getQuantity() {
 return quantity;
 }
 public void setQuantity(int quantity) {
 this.quantity = quantity;
 }
 public double getUnitPrice() {
 return unitPrice;
 }
 public void setUnitPrice(double unitPrice) {
 this.unitPrice = unitPrice;
 }
 public double getTotalMoney() {
 return totalMoney;
 }
 public void setTotalMoney(double totalMoney) {
 this.totalMoney = totalMoney;
 }
 public Product(String productId, String productName, int quantity,
 double unitPrice, double totalMoney) {
 super();
 this.productId = productId;
 this.productName = productName;
 this.quantity = quantity;
 this.unitPrice = unitPrice;
 this.totalMoney = totalMoney;
 }
 @Override
 public String toString() {
 return this.productName+"-"+(this.totalMoney);
 }

}

- Lớp Cate:


package tranduythanh.com;

public class Cate {
 private String cateId;
 private String cateName;
 public String getCateId() {
 return cateId;
 }
 public void setCateId(String cateId) {
 this.cateId = cateId;
 }
 public String getCateName() {
 return cateName;
 }
 public void setCateName(String cateName) {
 this.cateName = cateName;
 }
 public Cate(String cateId, String cateName) {
 super();
 this.cateId = cateId;
 this.cateName = cateName;
 }
 @Override
 public String toString() {
 return this.cateId.trim()+" - "+this.cateName.trim();
 }

}

- Lớp MainActivity:


package tranduythanh.com;

import java.util.ArrayList;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
 Button btngetlist;
 ListView lvcatalog;
 final String URL="http://testdrthanh.somee.com/mywebservice.asmx?WSDL";
 ArrayList<Cate> arrCate=new ArrayList<Cate>();
 ArrayAdapter<Cate>adapter=null;
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);
 lvcatalog=(ListView) findViewById(R.id.lvcatalog);
 btngetlist=(Button) findViewById(R.id.btnlistcatalog);
 btngetlist.setOnClickListener(new View.OnClickListener() {
 public void onClick(View arg0)
 {doGetList();}
 });
 adapter=new ArrayAdapter<Cate>
 (this, android.R.layout.simple_list_item_1, arrCate);
 lvcatalog.setAdapter(adapter);

 lvcatalog.setOnItemClickListener(new OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
 long arg3) {
 //xử lý hiển thị danh sách sản phẩm theo danh mục
 Cate c=arrCate.get(arg2);
 Intent in=new Intent(MainActivity.this, ListProductByCatalogActivity.class);
 in.putExtra("cateid", c.getCateId());
 startActivity(in);
 }
 });
 }

 public void doGetList() {
 try{final String NAMESPACE="http://tranduythanh.com/";
 final String METHOD_NAME="getListCatalog";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;
 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 envelope.setOutputSoapObject(request);
 //Nếu truyền số thực trên mạng bắt buộc phải đăng ký MarshalFloat
 //không có nó thì bị báo lỗi
 MarshalFloat marshal=new MarshalFloat();
 marshal.register(envelope);

 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 androidHttpTransport.call(SOAP_ACTION, envelope);
 //Get Array Catalog into soapArray
 SoapObject soapArray=(SoapObject) envelope.getResponse();
 arrCate.clear();
 //soapArray.getPropertyCount() return number of
 //element in soapArray
 //vòng lặp duyệt qua từng dòng dữ liệu
 for(int i=0; i<soapArray.getPropertyCount(); i++)
 {
 //(SoapObject) soapArray.getProperty(i) get item at position i
 SoapObject soapItem =(SoapObject) soapArray.getProperty(i);
 //soapItem.getProperty("CateId") get value of CateId property
 //phải mapp đúng tên cột:
 String cateId=soapItem.getProperty("CateId").toString();
 String cateName=soapItem.getProperty("CateName").toString();
 //đẩy vào array
 Cate c=new Cate(cateId, cateName);
 arrCate.add(c);
 }
 //xác nhận cập nhật giao diện
 adapter.notifyDataSetChanged();
 }
 catch(Exception e)
 {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
 }
 }
}

- Lớp ListProductByCatalogActivity:


package tranduythanh.com;

import java.util.ArrayList;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class ListProductByCatalogActivity extends Activity {
 ListView lvproduct;
 final String URL="http://testdrthanh.somee.com/mywebservice.asmx?WSDL";
 ArrayList<Product> arrProduct=new ArrayList<Product>();
 ArrayAdapter<Product>adapter=null;
 String cateId="";
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_list_product_by_catalog);

StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);
 lvproduct=(ListView) findViewById(R.id.lvproduct);

adapter=new ArrayAdapter<Product>
 (this, android.R.layout.simple_list_item_1, arrProduct);
 lvproduct.setAdapter(adapter);

 Intent in=getIntent();
 cateId= in.getStringExtra("cateid");
 }
 @Override
 protected void onResume() {
 // TODO Auto-generated method stub
 super.onResume();
 doGetListProduct();
 }
 public void doGetListProduct()
 {
 try{
 final String NAMESPACE="http://tranduythanh.com/";
 final String METHOD_NAME="getListProductByCatalogId";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;
 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
 request.addProperty("id", cateId);
 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 envelope.setOutputSoapObject(request);
 MarshalFloat marshal=new MarshalFloat();
 marshal.register(envelope);
 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 androidHttpTransport.call(SOAP_ACTION, envelope);

 //Get Array Catalog into soapArray
 SoapObject soapArray=(SoapObject) envelope.getResponse();
 arrProduct.clear();
 //soapArray.getPropertyCount() return number of
 //element in soapArray
 //vòng lặp duyệt qua từng dòng dữ liệu
 for(int i=0; i<soapArray.getPropertyCount(); i++)
 {
 //(SoapObject) soapArray.getProperty(i) get item at position i
 SoapObject soapItem =(SoapObject) soapArray.getProperty(i);
 //phải mapp đúng tên cột:
 String productId=soapItem.getProperty("ProductId").toString();
 String productName=soapItem.getProperty("ProductName").toString();
 String squantity=soapItem.getProperty("Quantity").toString();
 String sunitPrice=soapItem.getProperty("UnitPrice").toString();
 String stotalMoney=soapItem.getProperty("TotalMoney").toString();
 int quantity=Integer.parseInt(squantity);
 double unitPrice=Double.parseDouble(sunitPrice);
 double totalMoney=Double.parseDouble(stotalMoney);
 //đẩy vào array
 Product p=new Product(productId, productName, quantity, unitPrice, totalMoney);
 arrProduct.add(p);
 }
 //xác nhận cập nhật giao diện
 adapter.notifyDataSetChanged();
 }
 catch(Exception e) {}
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.list_product_by_catalog, menu);
 return true;
 }

}

- Quan sát dòng 55-56 đó là cách truyền Primivte data từ Android lên Webservice.

- Ta nên để trong OnReSume để đảm bảo rằng mọi thứ được sẵn sàng. Trong này sẽ lọc toàn bộ sản phẩm theo danh mục.

- Source code phần 3 ở đây: http://www.mediafire.com/download/3qyns57lzd2jjss/LearnWebservice_AddParameter_Primitive.rar

Các bạn chú ý phải làm lại nhiều lần bài 3 này vì nó khó và hay!

4) Cách truyền Object data từ Android tới .net web service

- Đây là phần cuối cùng Tui muốn hướng dẫn các bạn cách truyền Object Data từ Client Android lên Server thông qua Webservice.

- Ở bài tập 4 này bạn bổ sung thêm 1 hàm InsertCatalog vào Webservice, với đối số truyền vào là đối tượng Catalog:


//10 - thêm 1 catalog vào CSDL
 [WebMethod]
 public int insertCatalog(Catalog cate)
 {
 try
 {
 cate.Products.Clear();
 db.Catalogs.InsertOnSubmit(cate);
 db.SubmitChanges();
 }
 catch
 {
 return -1;
 }
 return 1;
 }

- Tui có giao diện đơn giản để demo cho phần này như sau:

2h46_9

- Khi nhấn nút “Show List Catalog”: Chương trình sẽ triệu gọi Webservice để hiển thị danh mục sản phẩm vào ListView bên dưới.

- Khi nhấn nút “Insert Cate”: Chương trình sẽ truyền đối tượng Catalog từ client lên Server thông qua Webservice. Ở đây Tui dùng cách truyền Properties cho tiện. Bạn chú ý phải quan sát kỹ Service Description của nó để truyền cho đúng Parameter:

2h46_9 2h46_10

- Tương tự như cho các hàm mà có truyền tham số khác cũng vậy, phải đặt đúng tên trong Service Descripton.

- Ta có XML Layout của ứng dụng như sau:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >

<TextView
 android:id="@+id/textView2"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#FFFF80"
 android:text="Input Catalog:"
 android:textSize="20sp" />

<TableLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >

<TableRow
 android:id="@+id/tableRow1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="#F0E7B3"
 android:text="Cate Id:" />

<EditText
 android:id="@+id/editcateid"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="text" >

<requestFocus />
 </EditText>
 </TableRow>

<TableRow
 android:id="@+id/tableRow2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<TextView
 android:id="@+id/textView2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="#F0E7B3"
 android:text="Cate Name:" />

<EditText
 android:id="@+id/editcatename"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:ems="10"
 android:inputType="text" />
 </TableRow>

<TableRow
 android:id="@+id/tableRow4"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" >

<Button
 android:id="@+id/btninsertcate"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_column="1"
 android:text="Insert Cate" />
 </TableRow>
 </TableLayout>

<TextView
 android:id="@+id/textView3"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="#FF80FF"
 android:text="Show List Catalog" />

<Button
 android:id="@+id/btnshowlist"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Show List Catalog" />

<ListView
 android:id="@+id/lvcatalog"
 android:layout_width="match_parent"
 android:layout_height="fill_parent" >
 </ListView>

</LinearLayout>

- Xử lý coding cho MainActivity như sau:


package tranduythanh.com;

import java.util.ArrayList;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.MarshalFloat;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import android.os.Bundle;
import android.os.StrictMode;
import android.renderscript.Mesh.Primitive;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity
 implements OnClickListener{
 EditText txtcateid,txtcatename;
 Button btninsertcate,btnlistcate;
 ListView lvlistcatalog;
 final String NAMESPACE="http://tranduythanh.com/";
 final String URL="http://testdrthanh.somee.com/mywebservice.asmx?WSDL";
 ArrayList<String> arrCate=new ArrayList<String>();
 ArrayAdapter<String>adapter=null;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

StrictMode.ThreadPolicy policy = new
 StrictMode.ThreadPolicy.Builder()
 .permitAll().build();
 StrictMode.setThreadPolicy(policy);

txtcateid=(EditText) findViewById(R.id.editcateid);
 txtcatename=(EditText) findViewById(R.id.editcatename);
 btninsertcate=(Button) findViewById(R.id.btninsertcate);
 btnlistcate=(Button) findViewById(R.id.btnshowlist);
 btninsertcate.setOnClickListener(this);
 btnlistcate.setOnClickListener(this);
 lvlistcatalog=(ListView) findViewById(R.id.lvcatalog);

adapter=new ArrayAdapter<String>
 (this, android.R.layout.simple_list_item_1, arrCate);
 lvlistcatalog.setAdapter(adapter);
 }

@Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }

@Override
 public void onClick(View v) {
 if(v==btnlistcate)
 {
 showlistcate();
 }
 else if(v==btninsertcate)
 {
 insertcate1();
 }
 }
 public void insertcate1()
 {
 try
 {
 final String METHOD_NAME="insertCatalog";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;

 SoapObject request=new SoapObject
 (NAMESPACE, METHOD_NAME);
 //tạo đối tượng SoapObject với tên cate như parameter trong service description
 SoapObject newCate=new
 SoapObject(NAMESPACE, "cate");
 //truyền giá trị cho các đối số (properties) như service desctiption
 newCate.addProperty("CateId",
 txtcateid.getText()+"");

 newCate.addProperty("CateName",
 txtcatename.getText()+"");
 request.addSoapObject(newCate);

 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 envelope.setOutputSoapObject(request);

 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 androidHttpTransport.call(SOAP_ACTION, envelope);
 //vì hàm insertCatalog trả về kiểu int
 SoapPrimitive soapPrimitive= (SoapPrimitive)
 envelope.getResponse();
 //chuyển về int để kiểm tra insert thành công hay thất bại
 int ret=Integer.parseInt(soapPrimitive.toString());

 String msg="Insert Cate Successful";
 if(ret<=0)
 msg="Insert Cate Failed";
 Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
 }
 catch(Exception e)
 {

}
 }//end insert cate
 public void showlistcate() {
 try
 {
 final String METHOD_NAME="getListCatalog";
 final String SOAP_ACTION=NAMESPACE+METHOD_NAME;
 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME);
 SoapSerializationEnvelope envelope=
 new SoapSerializationEnvelope(SoapEnvelope.VER11);
 envelope.dotNet=true;
 envelope.setOutputSoapObject(request);
 MarshalFloat marshal=new MarshalFloat();
 marshal.register(envelope);
 HttpTransportSE androidHttpTransport=
 new HttpTransportSE(URL);
 androidHttpTransport.call(SOAP_ACTION, envelope);
 //Get Array Catalog into soapArray
 SoapObject soapArray=(SoapObject) envelope.getResponse();
 arrCate.clear();
 //soapArray.getPropertyCount() return number of
 //element in soapArray
 for(int i=0; i<soapArray.getPropertyCount(); i++)
 {
 //(SoapObject) soapArray.getProperty(i) get item at position i
 SoapObject soapItem =(SoapObject) soapArray.getProperty(i);
 //soapItem.getProperty("CateId") get value of CateId property
 String cateId=soapItem.getProperty("CateId").toString();
 String cateName=soapItem.getProperty("CateName").toString();
 arrCate.add(cateId+" - "+cateName);
 }
 arrCate.add(soapArray.getPropertyCount()+" -- cate");
 adapter.notifyDataSetChanged();
 }
 catch(Exception e)
 {

}
 }
}

- Bạn có thể tải source code mẫu ở đây: http://www.mediafire.com/download/pvp59a21hc5fjhn/LearnWebservice_AddParameter_ObjectData.rar

- Như vậy Tui đã hướng dẫn đầy đủ 4 trường hợp thường gặp phải khi các bạn lập trình Android với .Net Webservice. Các bạn cần chú tâm nghiên cứu, ngoài ra cần tự học thêm JSON (JavaScript Object Notation) cho đủ bộ.

- Chúc các bạn thành công!

Bài 45: Sử dụng .Net Webservice trong C#


Ở bài tập 44, Tui đã trình bày cách tạo web service và cách đưa lên internet như thế nào.

Trong bài tập 45 này, Tui sẽ dùng C# để lấy dữ liệu từ server thông qua các service đã được cung cấp ở bài tập 44. Vậy những bạn nào chưa xem bài tập 44 thì bắt buộc phải xem lại.

Lý do Tui dùng C# trước là để các bạn dễ tưởng tượng ra cách thức lấy dữ liệu trên Webservice trước khi dùng KSOAP API trong Android để tương tác (vì tui cảm thấy nó hơi khó 1 xí).

Từ WebProject ở bài tập 44, bạn tạo thêm 1 Windows Form Project để lấy dữ liệu từ Service đó như sau:

1h45_0- Khi bấm Nút “Get List Catalog”: Chương trình sẽ triệu gọi web service (hàm getListCatalog) lưu trên http://testdrthanh.somee.com/mywebservice.asmx và hiển thị vào ListBox (listbox_cate)

- Khi chọn Catalog bất kỳ trong listbox_cate thì sẽ hiển thị danh sách sản phẩm thuộc danh mục đang chọn vào listbox_product.

- Khi bấm nút “Delete Selected Product”: Sẽ xóa Product đang chọn trong listbox_product.

Sau đây là cách lấy dữ liệu từ webservice ở trên:

1- Bấm chuột phải vào Project/ chọn Add Service Reference:

1h45_1

2- Màn hình chọn WebService hiển thị ra như bên dưới đây:

1h45_2

3- Bấm chọn nút “Advanced“:

1h45_3

4- Ở màn hình trên ta chọn “Add Web Reference…“:

1h45_4

Mục số 1: Ta copy dán đường dẫn webservice vào

Mục số 2 đặt tên cho Web Reference rồi nhấn nút “Add Reference“.

Sau khi bạn nhấn nút “Add Reference” thì Project sẽ được thay đổi như sau:

1h45_5

File app.config tự động xuất hiện và bên trong nó có thông tin sau:

1h45_6

- Bây giờ ta tiến hành Coding cho các control trên giao diện như sau:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestWebService
{
 public partial class Form1 : Form
 {
 public Form1()
 {
 InitializeComponent();
 }
 bool isFinish = false;
 com.somee.testdrthanh.mywebservice test = new com.somee.testdrthanh.mywebservice();
 //Nút hiển thị danh sách Catalog
 private void button1_Click(object sender, EventArgs e)
 {
 isFinish = false;

 List<com.somee.testdrthanh.Catalog> listCate = test.getListCatalog().ToList();
 listbox_cate.DataSource = listCate;
 listbox_cate.DisplayMember="CateName";
 listbox_cate.ValueMember="CateId";
 isFinish = true;
 }
 //xử lý hiển thị danh sách sản phẩm theo danh mục
 private void listbox_cate_SelectedIndexChanged(object sender, EventArgs e)
 {
 if (!isFinish) return;
 if (listbox_cate.SelectedItem != null)
 {
 com.somee.testdrthanh.Catalog cate = listbox_cate.SelectedItem as com.somee.testdrthanh.Catalog;
 List<com.somee.testdrthanh.Product> listProduct = test.getListProductByCatalogId(cate.CateId).ToList();
 listbox_product.DataSource = listProduct;
 listbox_product.DisplayMember = "ProductName";
 listbox_product.ValueMember = "ProductId";
 }
 }
 //xử lý nút xóa Product
 private void button2_Click(object sender, EventArgs e)
 {
 if (listbox_product.SelectedItem == null)
 return;
 DialogResult ret = MessageBox.Show("Muốn xóa Product này hả?", "Xác nhận xóa", MessageBoxButtons.YesNo);
 if (ret == DialogResult.Yes)
 {
 com.somee.testdrthanh.Product p = listbox_product.SelectedItem as com.somee.testdrthanh.Product;
 bool isDelete= test.deleteProduct(p.ProductId);
 if (isDelete)
 {
 com.somee.testdrthanh.Catalog cate = listbox_cate.SelectedItem as com.somee.testdrthanh.Catalog;
 List<com.somee.testdrthanh.Product> listProduct = test.getListProductByCatalogId(cate.CateId).ToList();
 listbox_product.DataSource = listProduct;
 listbox_product.DisplayMember = "ProductName";
 listbox_product.ValueMember = "ProductId";
 }
 else
 {
 MessageBox.Show("Không xóa được");
 }
 }
 }
 }
}

Khi thực thi thì ta có kết quả như sau:

1h45_7

- Bạn cố gẳng thử cho hết các Servive  được cung cấp ở trên.

- Các bạn có thể tải source code và CSDL ở đây: http://www.mediafire.com/download/9dubk49ukme269k/code_bai44_bai45.rar

- Bài tập sau các bạn sẽ được học cách lấy dữ liệu từ Web Service bằng thự viện KSOAP API trong Android.

- Chúc các bạn thành công

 

Follow

Get every new post delivered to your Inbox.

Join 458 other followers

%d bloggers like this: