VS/Xamarin Android入门(服务、数据存储)五

对于android的四大基本组件(Activity、Service、Broadcast Receiver、Content Provider),

前面已经介绍了Activity,最基本的活动单元,任何一个活动的处理,都需要他,前面介绍的对话框、布局、提示消息、基本内容设置等等。Broadcase Receiver,广播,主要是用于异步接受Intent(信使)今天我们来说一下 Service。

一、Service

  Service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。Service是在一段不定的时间运行在后台,不和用户交互应用组件。每个Service必须在manifest中 通过<service>来声明。可以通过contect.startservice和contect.bindserverice来启动。

  其中涉及的方法有:

    OnCreate:只会在服务第一次开启的时候调用,主要负责一些初始化代码。

    OnStartCommand:每次启动服务都会调用该方法,可能来自StartService或者由系统重启。一般负责开启需要长时间的任务。并且该方法还要返回StartCommandResult类型的枚举,该返回值将影响系统重启该服务的细节。

    OnDestroy:当服务使用StopSelf或者StopService时调用,主要用来释放资源等。

  需要说明的一点就是在Java里面写的时候,我们需要在AndroidManifest.xml里面添加服务,但是,在Xamarin里面,不需要这么复杂,我们直接在开头加上说明[Service]就可以了。其实就像一个简单的过滤器一样。其中过滤器在前面的隐式意图中已经提到。

[Service]
public  class  MainService : Service
{
}

  新建一个项目,然后再项目中添加一个类,直接加在根目录下面就可以MainService,然后继承Service,并且去实现他。

  首先要实现的是OnBind方法,这个方法是必须的,所以我们直接return null就可以。

public  override  IBinder OnBind(Intent intent)
    {
        return  null ;
    }

   然后说说涉及到的方法:OnCreate,这里的三个方法全都是重写的,因为,在Android里面,大部分的方法都是提供的,所以,一般情况下,我们需要做的就是实现各种接口。然后各种继承就可以。在添加的类里面添加如下方法。

public  override  void  OnCreate()
{
     base .OnCreate();
     Log.Debug( "xamarin" "OnCreate_create" );
}

   OnStartCommand,说一个简单的技巧,在IDE(VS全球最强大的IDE,没有之一,哈哈)直接override 方法名,然后直接按一次table键。自动补全的哦。

public  override  StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags,  int  startId)
{
     Log.Debug( "xamarin" "OnStartCommand_start" );
     return  StartCommandResult.Sticky;
}

   OnDestroy(),同样,我们直接在debug里面看就可以。

public  override  void  OnDestroy()
{
     base .OnDestroy();
     Log.Debug( "xamarin" "OnDestroy_stop" );
}

   OK,完整的服务代码我们已经建立完成了。如下

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
 
using  Android.App;
using  Android.Content;
using  Android.OS;
using  Android.Runtime;
using  Android.Views;
using  Android.Widget;
using  Android.Util;
 
namespace  Test022_Service
{
     [Service]
     public  class  MainService : Service
     {
         public  override  void  OnCreate()
         {
             base .OnCreate();
             Log.Debug( "xamarin" "OnCreate_create" );
         }
 
         public  override  StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags,  int  startId)
         {
             Log.Debug( "xamarin" "OnStartCommand_start" );
             return  StartCommandResult.Sticky;
         }
 
         public  override  void  OnDestroy()
         {
             base .OnDestroy();
             Log.Debug( "xamarin" "OnDestroy_stop" );
         }
 
         public  override  IBinder OnBind(Intent intent)
         {
             return  null ;
         }
     }
}

   接下来,我们就来添加界面代码,在Main.axml里面添加启动服务和停止服务的按钮。(Button即可)

<?xml version= "1.0"  encoding= "utf-8" ?>
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     android:orientation= "vertical"
     android:layout_width= "fill_parent"
     android:layout_height= "fill_parent" >
     <Button
         android:id= "@+id/startService"
         android:layout_width= "fill_parent"
         android:layout_height= "wrap_content"
         android:text= "启动服务"  />
     <Button
         android:id= "@+id/stopService"
         android:layout_width= "fill_parent"
         android:layout_height= "wrap_content"
         android:text= "停止服务"  />
</LinearLayout>

   对应的后台,直接启动即可,在前面的文中提到StartActivity,但是这里是启动服务,所以采用StartService即可,同样,停止服务,也是StopService。

protected  override  void  OnCreate(Bundle bundle)
{
     base .OnCreate(bundle);
     SetContentView(Resource.Layout.Main);
 
     Button start = FindViewById<Button>(Resource.Id.startService);
     start.Click += Start_Click;
 
     Button stop = FindViewById<Button>(Resource.Id.stopService);
     stop.Click += Stop_Click;
}
 
private  void  Stop_Click( object  sender, EventArgs e)
{
     Toast.MakeText( this "停止服务" , ToastLength.Short).Show();
     StartService( new  Intent( this typeof (MainService)));
}
 
private  void  Start_Click( object  sender, EventArgs e)
{
     Toast.MakeText( this "启动服务" , ToastLength.Short).Show();
     StopService( new  Intent( this typeof (MainService)));
}

   到这里,我们的Service已经完成。启动项目,在虚拟机中查看。

  如图,服务启动成功的时候怎么查看呢,这里只有一个提示信息而已,我们看一下IDE。

  点击我们这里的输出窗口。

  是不是可以看到了呢,在Service里面写的代码 Log.Debug().

  那么我们怎么知道到底那个服务启动了,那么我们来修改一下其中的代码即可

  OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags, int startId)

public  override  StartCommandResult OnStartCommand(Android.Content.Intent intent, StartCommandFlags flags,  int  startId)
       {
           Log.Debug( "xamarin" "OnStartCommand_start" );
           new  Thread(() =>
           {
               Log.Debug( "xamarin" , startId +  "号服务的线程启动" );
               Thread.Sleep(1000);
               Log.Debug( "xamarin" , startId +  "号服务的线程关闭" );
               StopSelf(startId);
           }).Start();
 
           return  StartCommandResult.Sticky;
       }

   那么,就有同学问了,这里的Thread到底是用 Java.Lang还是System.Threading呢,其实在这里是没区别的,因为都是启动一个线程

  OK,运行,查看输出窗口是不是可以看到呢。

二、Android数据存储

  在Android中,提供了SQLite数据库,它是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧,SQLiteDatabase类为我们提供了很多种方法,对于添加、更新和删除来说,我们都可以使用。

  我们来做一个测试。首先添加一个新的项目。

  首先在页面上添加一个按钮,用来创建和添加数据,等等。并且添加一个ListView来显示我们刚才添加的数据。

<?xml version= "1.0"  encoding= "utf-8" ?>
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     android:orientation= "vertical"
     android:layout_width= "fill_parent"
     android:layout_height= "fill_parent" >
     <Button
         android:id= "@+id/MyButton"
         android:layout_width= "fill_parent"
         android:layout_height= "wrap_content"
         android:text= "点击开始添加数据"  />
     <ListView
         android:minWidth= "25px"
         android:minHeight= "25px"
         android:layout_width= "match_parent"
         android:layout_height= "match_parent"
         android:id= "@+id/listView1"  />
</LinearLayout>

   然后,后台创建一个ArrayAdapter(数据适配器)去接受这些数据,并且显示在页面上。

  在这里如果我们要抛出异常的时候,最好用Android自带的SQLiteDatabaseCorruptException,不要用Exception,这个是捕捉不到异常的

using  System;
using  Android.App;
using  Android.Content;
using  Android.Runtime;
using  Android.Views;
using  Android.Widget;
using  Android.OS;
 
using  Android.Database.Sqlite;
using  Android.Database;
 
namespace  Test018
{
     [Activity(Label =  "添加数据库" , MainLauncher =  true , Icon =  "@drawable/myapk" )]
     public  class  MainActivity : Activity
     {
         protected  override  void  OnCreate(Bundle bundle)
         {
             base .OnCreate(bundle);
 
             // Set our view from the "main" layout resource
             SetContentView(Resource.Layout.Main);
 
             // Get our button from the layout resource,
             // and attach an event to it
             Button button = FindViewById<Button>(Resource.Id.MyButton);
             button.Click +=  delegate
             {
                 var  list = FindViewById<ListView>(Resource.Id.listView1);
                 list.Adapter = CreateLocalDb();
             };
         }
 
         private  ArrayAdapter< string > CreateLocalDb()
         {
             FindViewById<Button>(Resource.Id.MyButton).SetText(Resource.String.InsertDb);
             ArrayAdapter< string > adapter =  new  ArrayAdapter< string >( this , Android.Resource.Layout.SimpleListItem1);
             string  file =  "" ;
             try
             {
                 Random rand =  new  Random();
                 //
                 //创建数据库的时候的路径
                 //
                 using  (SQLiteDatabase db =  this .OpenOrCreateDatabase( "1.db" , FileCreationMode.Private,  null ))
                 {
                     db.ExecSQL( "create table IF NOT EXISTS T_Person(ID integer primary key autoincrement,Age integer,Name text)" );
                     for  ( int  i = 0; i < 5; i++)
                     {
                         var  item = rand.Next(10, 99);
                         db.ExecSQL( "insert into T_Person(Age,Name) values (?,?)" new  Java.Lang.Object[] { item,  "Jeff"  + item });
                     }
                     using  (ICursor cursor = db.RawQuery( " select * from T_Person " null ))
                     {
                         //ADO.Net.reader.Read() 读取数据
                         while  (cursor.MoveToNext())
                         {
                             int  id = cursor.GetInt(cursor.GetColumnIndex( "ID" ));
                             int  age = cursor.GetInt(cursor.GetColumnIndex( "Age" ));
                             string  name = cursor.GetString(cursor.GetColumnIndex( "Name" ));
                             adapter.Add(id +  ":我是"  + name +  ",我今年"  + age);
                         }
                     }
                     
                     //
                     //获取到当前的数据库路径
                     //
                     file =  this .GetDatabasePath( "1.db" ).Path;
                 }
             }
             //
             //SQLiteDatabaseCorruptException 抛出数据库异常
             //
             catch  (SQLiteDatabaseCorruptException e)
             {
                 e.ToString();
                 adapter.Add( "添加失败!" );
             }
             adapter.Add(file);
             return  adapter;
         }
     }
}

   如图,,可以根据部分注释去了解他们。我们运行一下,看下效果。要找路径的同学注意最后的哪一句,file = this.GetDatabasePath("1.db").Path;本程序已经在小弟我自己的Android手机上测试了,完全可行,哈哈。看虚拟机效果。直接点击按钮。

今天就到这里……

猜你喜欢

转载自www.cnblogs.com/xtxk110/p/12156348.html