您的位置:首页 > 移动开发 > Android开发

android基础入门

2015-09-21 21:20 501 查看

历史

2008年推出android1.0。

2011年10月,发布android4.0

概要

android系统架构

4层架构,5块区域

1. linux内核层

基于linux2.6内核,提供底层的驱动。

2. 系统运行库层

通过C/C++库提供主要特性支持。如sqlite,opengl,webkit,android运行时库(包括dalvik虚拟机)

3. 应用框架层

为应用程序提供api

4. 应用层

所有安装在手机上的应用程序,包括系统自带的。

搭建开发环境

需要的软件

jdk

android sdk

android studio

分析android程序

android studio基本项目结构

app/build

app模块build编译输出的目录

app/build.gradle

app模块的gradle编译文件

app/app.iml

app模块的配置文件

app/proguard-rules.pro

app模块proguard文件

build.gradle

项目的gradle编译文件

settings.gradle

定义项目包含哪些模块

gradlew

编译脚本,可以在命令行执行打包

local.properties

配置SDK/NDK

MyApplication.iml

项目的配置文件

External Libraries

项目依赖的Lib, 编译时自动下载的

app/main/java

源码目录

app/main/res

资源文件目录

核心文件解析

AndroidManifest.xml

注册activity,设置主活动。

Activity的java源文件

继承自Activity。

设置各阶段的业务代码

res目录

res/layout目录

存放所有的布局文件

res/mip*

用来存放图片

res/menu

用来放菜单文件

res/values

用来存放字符串

如何引用资源:

代码中用R.string.string_name

xml中用@string/string_name

使用日志

android中的日志工具类是Log(android.util.Log),提供了如下几种方法:

1. Log.v()

最琐碎,意义最小的日志

2. Log.d()

调试信息

3. Log.i()

info,打印一些比较重要的数据

4. Log.w()

警告信息

5. Log.e()

错误信息

活动(Activity)

包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含0个或者多个活动。

创建活动

新建一个类,继承自Activity,并重写onCreate()方法。

public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}


2.创建布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"
/>
</LinearLayout>


3.修改Activity代码

public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
}
}


4.在AndroidManifest文件中注册activity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activitytest"  >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".FirstActivity"
android:label="This is FirstActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /><!--设置项目入口-->
<category android:name="android.intent.category.LAUNCHER" /><!--设置为启动程序-->
</intent-filter>
</activity>
</application>
</manifest>


5.销毁Activity,修改button对应的事件。

Button b1 = (Button)findViewById(R.id.t1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});


目的(Intent)

使用显式intent

通过intent启动另一个activity。

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
}
});


使用隐式intent

1.通过activity标签的intent-filter指定当前activity可以响应的action和category。Action为系统中已经定义的一系列常用动作。Category属性用于指定当前动作(Action)被执行的环境。

<activity android:name=".SecondActivity" >
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START" /><!-- 自定义的action-->
<category android:name="android.intent.category.DEFAULT" /><!--必须加上这个,否则下面无法直接使用自定的action-->
</intent-filter>
</activity>


2.修改按钮的点击事件。

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);
}
});


更多隐式intent的用法

调用系统浏览器访问一个网页。

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});


ACTION_VIEW是android系统内置的动作。

向下一个活动传递数据

intent提供了一系列putExtra()方法的重载,用来暂存需要传递的数据。启动另一个intent后,从intent中取出数据即可。

传递方:

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
}
});


接收方

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", data);
}
}


这里的getStringExtra可以用getIntExtra(),getBooleanExtra()等方法代替。

返回数据给上一个活动

接收方

button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
}
});
....
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}


startActivityForResult的第二个整数用来唯一标识一次请求,传递方处理完数据后会传回给onActivityResult作为第一个参数。onActivityResult函数的第二个参数为返回码,用来判断处理是否成功,第三个参数为携带详细数据的intent。处理时一般先检查requestCode,判断数据来源。

传递方

public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.second_layout);
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return", "Hello FirstActivity");
setResult(RESULT_OK, intent);
finish();
}
});
}
}


setResult的值一般只使用RESULT_OK或RESULT_CANCLED。

活动的生命周期

返回栈

Android是用任务来管理活动。一个任务就是一组存放在栈里的活动的集合,称作返回栈。栈后进先出,默认启动的新活动位于栈顶,当按下back键或者调用finish()方法时,栈顶活动出栈,前一个活动处于栈顶,并显示给用户。

活动状态

每个活动生命周期中会有4种状态。

1.运行状态

当一个活动位于返回栈的栈顶时,处于运行状态

2.暂停状态

活动不再处于栈顶位置,但是仍然可见。内存极低时,有可能被系统回收资源。

3.停止状态

不处于栈顶,并且完全不可见。有可能被系统回收资源。

4.销毁状态

活动从返回栈移除后。系统最倾向于回收这类活动的资源。

活动的生存期

activity类定义了七个回调方法,覆盖了活动生命周期的每个环节。

1.onCreate()

活动第一次创建时调用,一般用来完成初始化等操作。

2.onStart()

在活动由不可见变成可见时调用

3.onResume()

在活动准备好和用户进行交互时调用。此时活动一定处于运行状态。

4.onPause()

在系统准备启动或者恢复另一个活动时调用。通常用来释放资源和保存数据。

5.onStop()

在活动完全不可见时调用。

6.onRestart()

在活动由停止变成运行状态前调用。

活动回收前的数据保存

activity提供了一个onSaveInstanceState()回调方法,保证一定在活动被回收之前调用。可以通过这个方法来保存数据。

1.保存数据

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String tempData = "Something you just typed";
outState.putString("data_key", tempData);
}


2.提取数据

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
Log.d(TAG, tempData);
}
......
}


活动的启动模式

1.standard

默认模式,每次都会重新创建活动,并放在栈顶。同一个activity会出现多个实例。

2.singleTop

创建活动时如果发现该活动已经是栈顶,则直接返回。

3.singleTask

如果返回栈里有该活动,则直接返回。

4.singleInstance

新建一个返回栈来管理该活动。

5.退出程序的做法

使用队列,将所有activity出队列。

public class ActivityCollector {
public static List<Activity> activities = new ArrayList<Activity>();
public static void addActivity(Activity activity) {
activities.add(activity);
}
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}


分别在oncreate和ondestroy中调用方法。

public class BaseActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity", getClass().getSimpleName());
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}


如果需要退出程序,调用ActivityCollector.finishAll()即可。

public class ThirdActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("ThirdActivity", "Task id is " + getTaskId());
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.third_layout);
Button button3 = (Button) findViewById(R.id.button_3);
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ActivityCollector.finishAll();
}
});
}
}


UI开发

常用android控件

1.textview

<TextView
android:id="@+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is TextView" />


2.button

<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />


3.edittext

<EditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>


4.imageview显示图片

<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
/>


5.progressbar进度条

<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>


6.alertdialog弹出对话框

AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("This is Dialog");
dialog.setMessage("Something important.");
dialog.setCancelable(false);
dialog.setPositiveButton("OK", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.setNegativeButton("Cancel", new DialogInterface.
OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
break;


7.progressdialog缓冲对话框

ProgressDialog progressDialog = new ProgressDialog
(MainActivity.this);
progressDialog.setTitle("This is ProgressDialog");
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(true);
progressDialog.show();


3)

四种基本布局

1.linearlayout

线性布局,垂直或者水平方向布局。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
......
</LinearLayout>


2.relativelayout

相对布局。指定它们相对于其父元素或兄弟元素的位置。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Button 1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Button 2" />
...
</RelativeLayout>


3.framelayout

所有控件都放在左上角。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
/>
<ImageView android:id="@+id/image_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" />
</FrameLayout>


4.tablelayout

使用表格的方式来排列控件。

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TableRow>
<TextView
android:layout_height="wrap_content"
android:text="Account:" />
<EditText
android:id="@+id/account"
android:layout_height="wrap_content"
android:hint="Input your account" />
</TableRow>
...
</TableLayout>


自定义控件

所有控件继承自view,所有布局继承自viewgroup。

view是android最基本的UI组件,可以在屏幕上绘制一块矩形区域并响应这块区域的各种事件,所有的控件都是在view的基础上添加了各自特有的功能。

viewgroup是一种特殊的view,可以包含很多子view和子viewgroup,是一个用于放置控件和布局的容器。

引入布局

为了避免布局文件大量重复。

1.创建一个布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_bg" >
<Button
android:id="@+id/title_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dip"
android:background="@drawable/back_bg"
android:text="Back"
android:textColor="#fff" />
</LinearLayout>


2.在需要的地方导入布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="@layout/title" />
</LinearLayout>


自定义控件

1.新建控件类

public class TitleLayout extends LinearLayout {
public TitleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title, this);
Button titleBack = (Button) findViewById(R.id.title_back);
Button titleEdit = (Button) findViewById(R.id.title_edit);
titleBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
titleEdit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getContext(), "You clicked Edit button",
Toast.LENGTH_SHORT).show();
}
});
}
}


2.在布局文件中使用新建的控件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.uicustomviews.TitleLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
></com.example.uicustomviews.TitleLayout>
</LinearLayout>


单位和尺寸

px表示像素,pt表示磅(1/72英寸)都会收到分辨率的影响。所以google引入了dp和sp。

dp是密度无关像素的意思,也称dip,在不同密度的屏幕中显示比例保持一致。

sp表示可伸缩像素,和dp概念一样,解决了文字大小适配问题。

android碎片

主要是用来处理大屏幕的访问问题,比如在平板上使用碎片显示更多的内容。

全局大喇叭

android中每个应用程序都可以对自己感兴趣的广播进行注册。

广播的类型

1.标准广播

是一种完全一部执行的广播,广播发出后,所有的广播接收器几乎同时收到广播消息,没有先后顺序,无法被截断。

2.有序广播

是同步执行的广播,发出后同一时刻只会有一个广播接收器能收到这条广播消息,该接收器的逻辑执行完毕后,广播继续传递。可以截断正在传递的广播。

接受系统的广播

1.动态注册广播

新建一个类,继承自BroadcastReceiver,并重写父类的onreceive()方法。oncreate中使用registerReceiver进行注册,在ondestroy方法中调用unregisterreceiver方法取消注册。动态注册的广播一定要取消注册。

public class MainActivity extends Activity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "network changes",
Toast.LENGTH_SHORT).show();
}
}
}


2.静态注册实现开机启动

动态注册的问题在于必需要启动后才能接受到广播。静态注册可以在程序未启动时接收广播。

1)新建类,继承自BootCompleteReceiver。

public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}


2)在AndroidManifest.xml 中将这个广播接收器的类名注册进去。

这里出现了新的标签,所有静态注册的广播接收器都在这里进行注册。别忘了还要申请相应的权限。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest"
android:versionCode="1"
android:versionName="1.0" >
......
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
......
<receiver android:name=".BootCompleteReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>


发送自定义的广播

1.发送标准广播

Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);


2.发送有序广播

Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent, null);


阻止有序广播继续传播

public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceive",Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}


3.使用本地广播

android引入了一套本地广播机制,所发出的广播只能在应用程序内部进行传递,并且本地广播接收器也只能接收来自本应用程序发出的广播,避免了安全性的问题。

区别:使用LocalBroadcastManager获取实例,发送和注册广播接收器时均使用该实例的方法。

localBroadcastManager = LocalBroadcastManager.getInstance(this);
// 获取实例
...
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
localReceiver = new LocalReceiver();
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
// 注册本地广播监听器
...
Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent); // 发送本地广播
...
localBroadcastManager.unregisterReceiver(localReceiver);//注销广播
...
class LocalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received local broadcast",
Toast.LENGTH_SHORT).show();
}
}


数据存储全方案

android提供了3种方式用于简单地实现数据持久化功能。

1.文件存储

2.sharedpreference存储

3.数据库存储

文件存储

写文件

context类提供了一个openFileOutput方法,接收2个参数。

1.文件名,不包含路径。文件默认存储到/data/data/”package-name”/files/目录下。

2.模式。MODE_PRIVATE 和 MODE_APPEND。覆盖写和追加写。

FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(data);
} catch (IOException e) {
e.printStackTrace();
}


读文件

FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();


SharedPreferences存储

使用键值的方式来存储数据。SharedPreferences文件都是存放在/data/data/”package-name”/shared_prefs/目录下的,以xml格式进行管理。

三种获取SharedPreferences对象的方法

1.context类的getSharedPreferences()方法

第一个参数指定文件名。

第二个参数指定操作模式,MODE_PRIVATE 和MODE_MULTI_PROCESS。MODE_PRIVATE 是默认的操作模式,和直接传入 0 效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences 文件进行读写。 MODE_MULTI_PROCESS 则一般是用于会有多个进程中对同一个 SharedPreferences 文件进行读写的情况。

2.Activity 类中的 getPreferences()方法

只接收一个参数,指定操作模式。文件名默认为当前活动的类名。

3.PreferenceManager 类中的 getDefaultSharedPreferences()方法

只接收一个参数,指定操作模式。文件名默认为当前应用程序包名。

写入

1.调用SharedPreferences对象的edit方法获取Editor对象。

2.向edit对象添加数据

3.调用commit方法提交数据,完成存储。

SharedPreferences.Editor editor =getSharedPreferences("data",
MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.commit();


读取

SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "age is " + age);
Log.d("MainActivity", "married is " + married);


sqlite数据库存储

SharedPreferences存储只适用于保存一些简单的数据,当需要进行大量复杂的存储时,需要使用sqlite。

数据库文件会存放在/data/data/”package-name”/databases/目录下。

1.创建数据库

1)新建类,继承自SQLiteOpenHelper,重写oncreate和onupgrade方法。

oncreate方法只会在创建数据库时执行一次,onupgrade在每次修改数据库版本号后执行一次。

SQLiteOpenHelper 构造方法中接收四个参数,

第一个参数是 Context,

第二个参数是数据库名,

第三个参数允许我们在查询数据的时候返回一个自定义的 Cursor,一般都是传入 null。

第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。(新建或者修改表等操作后,增加该值。)

public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
onCreate(db);
}
}


2)调用该类,创建库。

private MyDatabaseHelper dbHelper;
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});


2.插入数据

private MyDatabaseHelper dbHelper;
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
...
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values); // 插入第一条数据
values.clear();
// 开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 510);
values.put("price", 19.95);
db.insert("Book", null, values); // 插入第二条数据


3.更新数据

values.put("price", 10.99);
db.update("Book", values, "name = ?", new String[] { "The DaVinci Code" });


4.删除数据

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "500" });


5.查询数据

query参数详情:

1)表名

2)需要查询的列

3)指定where的约束条件

4)为where中占位符提供具体的值

5)指定需要group by的列

6)对group by后的结果进一步约束

7)指定查询结果的排序方式

SQLiteDatabase db = dbHelper.getWritableDatabase();
// 查询Book表中所有的数据
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
// 遍历Cursor对象,取出数据并打印
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity", "book name is " + name);
Log.d("MainActivity", "book author is " + author);
Log.d("MainActivity", "book pages is " + pages);
Log.d("MainActivity", "book price is " + price);
} while (cursor.moveToNext());
}
cursor.close();


6.使用sql操作数据库

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
db.rawQuery("select * from Book", null);


7.使用事务

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransaction(); // 开启事务
....
db.endTransaction(); // 结束事务


跨程序共享数据

内容提供器

主要用于在不同应用程序之间实现数据共享的功能。

1.现有的内容提供器

android系统自带的电话薄等程序都提供了类似的访问接口。

内容 URI 是内容提供器中数据的唯一标识符,由两部分组成:权限(authority)和路径(path)。

权限是用于区分不同的应用程序,为了避免冲突,都会采用程序包名的方式来进行命名。比如某个程序的包名是 com.example.app,那么该程序对应的权限就可以命名为com.example.app.provider。

路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。

最后,还需要在字符串的头部加上协议声明。

1)声明权限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.contactstest"
android:versionCode="1"
android:versionName="1.0" >
......
<uses-permission android:name="android.permission.READ_CONTACTS" />
......
</manifest>


2)获取数据

Cursor cursor = null;
// 查询联系人数据
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, null, null, null);
while (cursor.moveToNext()) {
// 获取联系人姓名
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
// 获取联系人手机号
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
cursor.close();


2.创建自己的内容提供器

1)新建一个类,继承自ContentProvider,重写6个抽象方法。

public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
return 0;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
}


运用手机多媒体

1.使用通知

NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "This is ticker text", System.currentTimeMillis()); //第一个参数指定图片,第二个指定ticker内容,第三个指定通知创建时间
....
Intent intent = new Intent(this,NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);//创建延迟intent
....
Uri soundUri = Uri.fromFile(new File("/system/media/audio/ringtones/Basic_tone.ogg"));
notification.sound = soundUri;//让通知发生的时候播放一段音频
notification.setLatestEventInfo(this, "This is content title","This is content text", pi);//第二个参数指定标题,第三个指定内容,第四个
manager.notify(1, notification);


2.接收和发送短信

使用intent和系统提供的功能进行交互

3.调用摄像头和相册

File outputImage = new File(Environment.
getExternalStorageDirectory(), "tempImage.jpg");
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
imageUri = Uri.fromFile(outputImage);
Intent intent = new Intent("android.media.action. IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, TAKE_PHOTO); // 启动相机程序


4.播放多媒体文件(音频和视频)

后台服务

服务的生命周期

1.context调用startService方法,服务启动。

2.如果服务未创建过,oncreate方法执行。

3.执行onStartCommand方法

4.服务处理完毕,调用stopService或者stopSelf方法。

5.ondestroy方法执行

注意,只有服务取消绑定后才能被销毁。

context.startService() -> onCreate() -> onStart() -> Service running -> context.stopService() -> onDestroy() -> Service stop

服务的基本使用

1)定义server

public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}


2)修改 AndroidManifest.xml文件

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicetest"
android:versionCode="1"
android:versionName="1.0" >
......
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
......
<service android:name=".MyService" >
</service>
</application>
</manifest>


3)启动服务

Intent startIntent = new Intent(this, MyService.class);
startService(startIntent); // 启动服务


4)停止服务

Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent); // 停止服务


活动与服务通信

1)server类中新建binder类的子类

public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
......
}


2)定义一个connection类。提供一个ServiceConnection的实现,用以监控与服务Service间的连接情况。

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
};


3)绑定服务

bindService()无返回值,但系统在客户端与服务端连接之间,会调用在ServiceConnect对象中的onServiceConnected()方法

Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务


前台服务

在通知栏显示服务进程,避免因内存不足导致进程关闭。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android