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. 应用层
所有安装在手机上的应用程序,包括系统自带的。
搭建开发环境
需要的软件
jdkandroid sdk
android studio
分析android程序
android studio基本项目结构
app/buildapp模块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)定义serverpublic 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); // 绑定服务
前台服务
在通知栏显示服务进程,避免因内存不足导致进程关闭。相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories