原文: Android(Xamarin)之旅(五)

2016年1月23日,北京迎来了很痛苦的一天,冻死宝宝了,一天都没有出我自己的小黑屋,在这屋子里自娱自乐。不知道你们呢

对于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手机上测试了,完全可行,哈哈。看虚拟机效果。直接点击按钮。

  是不是感觉自己很帅气的样子,其实我就是这么想的。

  看到这篇文章的妹纸,汉字,点一下您那可爱的小手,给推荐一下,小弟这厢有礼了。

  

更多相关文章

  1. Android中Intent,service,broadcast应用浅析
  2. Android事件分发与消费
  3. Android(安卓)图片压缩也即生成缩略图方法
  4. 《宅男的android开发指南》(翻译)--7
  5. Android(安卓)数据存储(一) Preference的使用
  6. android app启动流程解析
  7. Android(安卓)Context对象
  8. 隐藏Android(安卓)系统自带的v7.widget.Toolbar的标题
  9. Android数据库SQLite性能优化技巧

随机推荐

  1. 90题细品吴恩达《机器学习》,感受被刷题支
  2. 谈谈统计学正态分布阈值原理在数据分析工
  3. 学Flask框架有什么用?为什么学习Flask?
  4. n种方式教你用python读写excel等数据文件
  5. AKS网络模型介绍及创建技巧
  6. Python地信专题 | 基于geopandas的空间数
  7. 好看不火 | 怎么才有数据分析思路?
  8. 案例 | 用pdpipe搭建pandas数据分析流水
  9. centos7 安装python3.8
  10. Python地信专题 | 基于geopandas的空间数