本文基于:Androd第一行代码-郭霖
一、Android基本工具
1、repo
repo只是google用Python脚本写的调用git的一个脚本,主要是用来下载、管理Android项目的软件仓库。
repo init –u URL 用以在当前目录安装repository,会在当前目录创建一个目录".repo"
-u参数指定一个URL从这个URL中取得repository的manifest文件。这个文件的内容其实就是所有被git管理的仓库的列表!
-m参数来选择获取repository中的某一个特定的manifest文件
-b参数来指定某个manifest分支
repo sync 抓取android source code
2、Android SDK目录结构及作用
build-tools:各版本编译工具
platforms:各版本SDK, 根据API Level划分的SDK版本
platforms-tools:各版本SDK通用工具,如包含开发app的平台依赖的开发和调试工具,包括adb、fastboot
tools:各版本SDK自带工具。包含了重要的工具,比如DDMS用于启动Android调试工具,
比如LoaCat、屏 幕截图和文件管理器,而draw9patch则是绘制Android 平台的可缩放png图片的工具
AVDManager:Android手机模拟配置工具,用于配置模拟器,只有先配置AVD才可运行模拟器。
SDKManager:SDK管理器,用于SDK更新、下载、删除。
system-images:模拟器映像文件。从android-14开始将模拟器映像文件整理在这里(原来放在platforms下)
add-ons:oogle API 。比如GoogleMaps
3、第一行代码书中代码下载
https://github.com/guolindev/booksource
4、Application
Android系统运行时,系统会创建Application来存储系统信息。
二、Activity
1、声明主活动
<activity
android:name=".FirstActivity"
android:label="FirstActivity">
<intent-filter>
//指定其为主活动
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2、毁掉活动
自己调用:finish();
3、Intent
显式:
启动A启动B
Intent intent = new Intent(A_Activity.this, B_Activity.class);
StartActivity(intent);
隐式:
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
只有<action>和<category>中的内容能同时匹配上,该Activity才能响应。每个Intent只能指定一个action但能指定多个category
<activity
android:name=".SecondActivity"
android:label="SecondActivity">
<intent-filter>
<actionandroid:name="com.example.activitytest.ACTION_START" />
<categoryandroid:name="android.intent.category.DEFAULT" />
<categoryandroid:name="com.example.activitytest.MY_CATEGORY" />
</intent-filter>
</activity>
Activity之间传递数据
向下一个活动传递数据
A_Activity:
String data = "Hello SecondActivity";
Intentintent = new Intent(FirstActivity.this, SecondActivity.class);
//给要发送的数据指定键
intent.putExtra("data_of_send",data);
startActivity(intent);
B_Activity:
//获取数据
Intentintent = getIntent();
Stringdata = intent.getStringExtra("data_of_send");
Log.d("SecondActivity",data);
返回数据给上一个活动
A_Activity:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
StartActivityForResult(intent, 1);//1是请求码
//当活动B销毁,活动A执行下面方法
Protected voidonActivityResult(int requestCode, int resultCode, Intent data){
Switch(requestCode){
Case 1:
If(resultCode == RESULT_OK){
String resultData =data.getStringExtra(“data_return”);
}
Break;
Default;
}
}
B_Activity:
Intent intent = new Intent();
//给要发送的数据指定键
intent.putExtra("data_of_send",data);
setResult(RESULT_OK,intent);
finish();
4、活动的生命周期:
onCreate(), onSart(), onResume(),onPause(), onStop(),onDestroy(), onRestart()
onResume():在活动准备好和用户交互时调用。此时活动一定处于栈顶,运行状态。
活动刚启动依次执行:onCreate(), onSart(), onResume()
onPause(), onStop()的区别在于,onPause用于关掉对话框式的活动。
数据保存:
活动被回收前一定会调用onSaveInstanceState(Bundle outState), Bundle参数提供了一系列的方法用于保存数据。
Protected void onSaveInstanceState(Bundle outState){
Super.onSaveInstanceState(outState);
StringtempData = “sfs fsdf ”;
Outstate.putString(“key”,tempData);
}
恢复数据:
Protected void onCreate(Bundle savedInstanceState){
Super.oncreate(savedInstanceState);
setContentView(R.layout.activity);
if(savedInstanceState!= null){
StringtempData = savedInstance.getString(“key”);
Log.d(TAG,tempData);
}
}
5、活动的启动模式:
standard, singleTop, singleTask,singleInstance
需要在AndroidManifest.xml的Activity相中指定,Standard模式不需要指定
<activity
android:name=".SecondActivity"
android:label="SecondActivity"
android:launchMode=”singleTop”>
</activity>
三、UI
TextView
Button
EditText
ImageView
ProgressBar
AlertDialog, ProgressDialog类似,后者会在对话框中显示一个进度条,表示当前操作比较耗时,让用户等待。
ListView,RecyclerView
四种基本布局:LinearLayout, RelativeLayout, FrameLayout,PercentFrameLayout
五、Broadcast Receiver
1、分类
标准广播:发出后所有广播接收器同时收到。
有序广播:接收存在优先级,前级可以控制是否继续向下广播。
2、注册
动态注册:在代码中注册。
动态注册测试自由注册和销毁但是必须在程序启动后才能接收到广播。
注意权限问题
public class MainLayoutActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
protected void onCreate(Bundle savedInstanceState) {
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = newNetworkChangeReceiver();
registerReceiver(networkChangeReceiver,intentFilter);
}
protected voidonDestroy(){
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
//继承BroadcastReceiver重写onReceive
classNetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intentintent){
ConnectivityManager con =(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo =con.getActiveNetworkInfo();
if(networkInfo != null &&networkInfo.isAvailable())
Toast.makeText(context,"network is available", Toast.LENGTH_SHORT).show();
else
Toast.makeText(context,"network is unavailable", Toast.LENGTH_SHORT).show();
}
}
}
静态注册:在AndroidManifest.xml中注册。
1. 新建BoardcastReceiver文件
public class BootCompleteReceiver extendsBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete",Toast.LENGTH_LONG).show();
}
}
2. 在AndroidManifest.xml中注册
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED" >
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<actionandroid:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3、发送自定义广播
发送方:
Intent intent = new Intent(“com.example.boardcasttest.MY_BOARDCAST”);
sendBoardcast(intent);
接收方:
<intent-filter>
<actionandroid:name=" com.example.boardcasttest.MY_BOARDCAST " />
</intent-filter>
4、发送有序广播
1、sendOrderedBoardcast(intent,null);优先级高的在接收到广播之后可以abortBoardcast()停止广播。
2、修改AndroidManifest.xml
<intent-filter android:priority=”100”>
<actionandroid:name=" com.example.boardcasttest.MY_BOARDCAST " />
</intent-filter>
5、使用本地广播
只在APP内部传输
private LocalBoardcastManager localBoardcastManager;
localBoardcastManager = LocalBoardcastManager.getInstance(this);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
localReceiver = new localReceiver ();
registerReceiver(localReceiver,intentFilter);
Intent intent = new Intent(” com.example.boardcasttest.MY_BOARDCAST”);
localBoardcastManager.sendBoardcast(intent);
六、数据存储
文件存储、SharedPreference、数据库
1、文件存储
Context类提供openFileOutput()返回FileOutputStream对象,可供java流将数据写入文件。数据存到指定文件中/data/data/<packagename>/files/下。
写文件:
public void save(string data){
FileOutputStream mFileOutputStream =null;
BufferedWriter mBufferedWriter = null;
try{
mFileOutputStream= openFileOutput(“data”, Context.MODE_PRIVATE);
mBufferedWriter = new BufferedWriter(newOutputStreamWriter(MFileOutputStream));
mBufferedWriter.write(data);
}catch(IOExcept e){
e.printStackTrace();
}finally {
try{
if(write != null){
mBufferedWriter.close();
} cache (IOExcept e){
e.printStackTrace();
}
}
}
}
读文件:
public String load(){
FileInputStream mFileInputStream = null;
BufferedReader mBufferedReader = null;
StringBuilder mStringBuilder = new StringBuilder();
try{
mFileInputStream= openFileInput(“data”);
mBufferedReader =
new BufferedReader(new InputStreamWriter(mFileInputStream));
String sline = “”;
while((line = mBufferedReader.readLine())!= null){
mStringBuilder.append(mline);
}
}catch(IOExcept e){
e.printStackTrace();
}finally {
try{
If(mBufferedReader!= null){
mBufferedReader.close();
} cache (IOExcept e){
e.printStackTrace();
}
}
}
Return context.toString();
}
2、SharedPreference
SharedPreference文件存于/data/data/<package_name>/shared_prefs/下
(1)首先要获得SharedPreference对象,有3种方法可以获取:
Context类中的getSharedPreferences;Activity类中的getSharedPreferences;PreferenceManager类中的getSharedPreferences
(2)调用SharedPreference对象的edit()获取SharedPreference.Editor对象。
(3)向SharedPreference.Editor添加数据,用putString()等方法。
(4)调用apply()提交数据,完成操作。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button saveData = (Button) findViewById(R.id.save_data);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.apply();
}
});
Button restoreData = (Button) findViewById(R.id.restore_data);
restoreData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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);
}
});
}
3、SQLite数据库存储
创建后的数据库位于:/data/data/<package_name>/databases/下
Android提供SQLiteOpenHelper帮助类对数据库进行创建和升级。创建类继承它,重写onCreate(), onUpgrade()。还提供getReadableDatebase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库。一个库中可以创建多张表。
新建类继承SQLiteOpenHelper
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "//id 为主键,递增
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";
private Context mContext;
//第二个参数为数据库名,第三个为位置,第四个为版本号,升级时用
public MyDatabaseHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
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");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
第一次点击按钮时没有该库就会创建它
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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); // 插入第二条数据
}
});
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
//? = The Da Vinci Code, 更新name=?的内容
db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
}
});
Button deleteButton = (Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "500" });
}
});
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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"));
} while (cursor.moveToNext());
}
cursor.close();
}
});
}
}
也可以直接通过SQL来操作数据库
添加数据:
db.execSQL("insert into Book (name, author, pages, price) value(?, ?, ?, ?)", new String[] {"The Da Vinci Code", "Dan Brown", "454", "16.96"})
更新数据:
db.execSQL("update Book set price = ? where name = ?", new String[] {"10.99", "The Da Vinci Code"});
删除数据:
db.execSQL("delete from Book where pages > ?", new String[] {"500"});
查询数据:
db.rawQuary("select * from Book", null);