Android平臺架構:
安卓平臺架構 | |
---|---|
Applications (應用程序) | - |
Applications Framework (應用程序框架) | - |
Android Runtime(android 運行時) | Libraries (庫) |
Linux Kernel (linux內核) | - |
應用程序提供一組應用程序。java編寫。我們再此開發
開發的程序都是基于Applications Framework,簡化代碼編寫/提高程序復用性
Libraries提供一組C/C++的庫,開發人用可通過Applications Framework使用
Android 運行時包括核心庫和Dalvik虛擬機,核心庫包含java核心庫大部分功能,虛擬機負責運行程序
Android采用Linux 2.6 內核提供的核心服務,包括安全性,內存管理,進程管理
Android四大組件:
Activity、Service、Broadcast Receiver、Content Provider
Android項目結構:
src包:應用程序的源代碼
gen包:包含由ADT生成的java文件(R.java AIDL文件創建的接口)【R.java也在這】
android.jar: 包含了Android項目所需要使用的工具類
assets包:用于保存原始資源文件,其中的文件會編譯到.apk,并且原文件名會被保存(通常用于保存文本,游戲數據)
res包:保存資源文件,當該包中文件發生變化,R文件會自動修改
drawable:用來保存圖片(有幾個是因為保存高,中,低)
layout:保存應用布局文件
values:保存應用中使用的字符串
AnodroidManifest.xml 文件:每個程序必須有一個,位于根目錄,表明Activity,Service信息等配置信息
project.properties文件:包含項目屬性
adb命令:
adb devices //查詢模擬器
adb -s em-001 install test.apk //在em-001上安裝test.apk
adb install d:\test.apk //安裝d盤的test.apk
adb push <local> <remote> //將本地文件復制到設備
adb pull <remote> <local> //將設備文件復制到本地
android 可以有多個Activity,他們組成棧,當前活動位于棧頂,之前的活動被壓入棧底,成為非活動Activity
Activity生命周期:
onCreate(): 創建activity時被調用
onStart(): 啟動activity時被調用,Activity變為顯示時候被調用
onRestart(): 重新啟動activity時候被調用,該方法總是在onStart()之后被調用
onPause:暫停Activity時被調用,通常涉及持久化保存數據
onResume:當Activity從暫停變為活動時候被調用
onStop: 停止Activity調用
onDestory:摧毀Activity調用
Activity中經常重寫onCreate()和onPause()2個方法
創建一個Activity類
import android.app.Activity
public MainActiviy extends Activity{
}
//我們同時也要重寫onCreate方法
@Override
public void onCreate(Bundle savedlnstanceState){
surper.onCreate(savedlnstanceState);
setContentView(R.layout.main);//設置要顯示的視圖
}
配置Activity
創建完成后,還要在AndroidManifest.xml中進行配置
<application>
<activity
android:icon="@drawable/ic_lancher"
android:name="DetailActivity" //name指定對應的Activity實現類
android:label="詳細"
>
</activity>
</application>
啟動/關閉Activity
//啟動
Intent intent = new Intent(MainActivity.this,DeatilActivity.class);
startActvity(intent) //啟動活動
//關閉
finsh() //在Activity中執行 關閉
Activity中的傳參問題
使用Bundel在Activity之間交換數據:
先將數據存入Bundel,再將Bundel存入Intent,Intent再在不同的Activity間傳遞。
//Bundle 存值
Intent intent = new Intent(MainActivity.this,DeatilActivity.class);
Bundle bundle = new Bundle();
bundle.putCharSequence("name","HOUN");
bundle.putCharSequence("pwd","123456");
intent.putExtras(bundle);
startActivity(intent);
//Bundle 取值
Intent intent = getIntent();
Bundle bundle= intent.getExtras();
String name = bundle.getString("name");
String pwd = bundle.getString("pwd");
//關閉某個Activity后返回
//打開Activity代碼 替換為 startActivityForResult(intent,CODE)
//在要返回的Activity中的finish()前加
setResult(0x717,intent)
//然后在第一個Activity里重寫onActivityResult方法
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
super.onActivityResult(requestCode,resultCode);
if(requestCode==0x717 && resultCode==0x717){
Bundle bundle=data.getExtras();
/**繼續你的操作*/
}
}
布局管理器
-
線性布局
<LinearLayout></LinearLayout>
組件按水平或垂直方向;
android:orientation=(horizontal(水平)/ vertical(垂直,默認))
android:gravity (布局管理器內組件的對齊方式)
-
表格布局
<TableLayout> </TableRow></TableRow> </TableLayout>
</TableRow>占一行,繼承線性布局
幀布局
```
<FrameLayout></FrameLayout>
```
默認從左上腳(0,0)處開始,層疊排序,后面會覆蓋前面的
- 相對布局
<RelativeLayout></RelativeLayout>
線性布局
Intent
Intent(意圖)主要是解決Android應用的各項組件之間的通訊
實際上Activity Service Broadcast Receiver 這3個核心組件都需要Intent來激活
Intent包含
1. 組件名稱
2. 動作 setAction() //設置 getAction()//讀取
3. 數據
4. 種類
5. 額外:putExtras() 和 getExtras() 作為Bundle的設置和讀取
6. 標記
Intent的兩種用法:
(1). 顯式的Intent,即在構造Intent對象時就指定接收者.
eg:
Intent it = new Intent(Activity.Main.this, Activity2.class);
startActivity(it);
上面那個intent中, 直接指明了接收者:Activity2
(2).隱式的Intent,即Intent的發送者在構造Intent對象時,并不知道也不關心接收者是誰,有利于降低發送者和接收者之間的耦合,它一般用在沒有明確指出目標組件名稱的前提下,一般是用于在不同應用程序之間.
eg:
Intent it = new Intent();
it.setAction("com.google.test");
startActivity(it);
上面那個intent, 沒有指明接收者, 只是給了一個action作為接收者的過濾條件。
對于顯式Intent,Android不需要去做解析,因為目標組件已經很明確,Android需要解析的是那些隱式Intent,通過解析,將Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。
<intent-filter>
<action android:name="com.google.test" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
//android.intent.action.MAIN決定一個應用程序最先啟動那個組件
//android.intent.category.LAUNCHER決定應用程序是否顯示在程序列表里(說白了就是是否在桌面上顯示一個圖標)
注意: 每一個通過 startActivity() 方法發出的隱式 Intent 都至少有一個 category,就是 "android.intent.category.DEFAULT",所以只要是想接收一個隱式 Intent 的 Activity 都應該包括 "android.intent.category.DEFAULT" category,不然將導致 Intent 匹配失敗.
Intent的過濾器(intent-filter),按照以下優先關系查找:action->data->category
AndroidManifest.xml
AndroidManifest.xml文件詳解
聲明程序中的Activities, ContentProviders, Services, 和Intent Receivers,還能指定permissions和instrumentation(安全控制和測試)
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<!-- 基本配置 -->
<uses-permission />
<permission />
<permission-tree />
<permission-group />
<instrumentation />
<uses-sdk />
<uses-configuration />
<uses-feature />
<supports-screens />
<compatible-screens />
<supports-gl-texture />
<!-- 應用配置 -->
<application>
<!-- Activity 配置 -->
<activity>
<intent-filter>
<action />
<category />
<data />
</intent-filter>
<meta-data />
</activity>
<activity-alias>
<intent-filter> . . . </intent-filter>
<meta-data />
</activity-alias>
<!-- Service 配置 -->
<service>
<intent-filter> . . . </intent-filter>
<meta-data/>
</service>
<!-- Receiver 配置 -->
<receiver>
<intent-filter> . . . </intent-filter>
<meta-data />
</receiver>
<!-- Provider 配置 -->
<provider>
<grant-uri-permission />
<meta-data />
</provider>
<!-- 所需類庫配置 -->
<uses-library />
</application>
</manifest>
<uses-permission> //來指定權限開發
eg:
<uses-permission android:name="android.permission.INTERNET"/> //開放網絡
<uses-permission android:name="android.permission.CAMERA"/> //開放照相機
<permission> //權限聲明標簽
<uses-library> //用于指定Android應用可使用的用戶庫
<application> //應用配置的根元素,位于<manifest>下層,包含所有與應用有關配置的元素
<activity> //Activity活動組件(即界面控制器組件)的聲明標簽,Android應用中的每一個Activity都必須在AndroidManifest.xml配置文件中聲明.標簽中常用的屬性有:Activity對應類名android:name,對應主題android:theme,加載模式android:launchMode,另外,<activity>標簽還可以包含用于消息過濾的<intent-filter>元素
<intent-filter> //用于Intent消息過濾器的聲明
<service> //Service服務組件的聲明標簽
<receiver> //Boardcast Receiver廣播接收器組件的聲明標簽,用于定義與描述一個具體的Android廣播接收器
<provider> //Content Provider內容提供者的聲明標簽
Content Provider
Content Provider 用于保存和獲取數據(對所有應用可見)
一般使用ContentResolver對Content Provider進行操作
ContentResolver cr = getContentResolver();
content:// 模式表示數據由Content Provider來管理
URI | |||
---|---|---|---|
content:// | com.test.emprovider | /abc | /001 |
A | B | C | D |
標準的前綴 | authority部分(<provider>要聲明),用于識別Content Provider | Content Provider路徑部分 | ID值 |
使用預定義的Content Provider
ContentResolver rs = getContentResolver();
Cursor cursor = rs.query();
使用自定義的Content Provider
首先重寫6個方法
public boolean onCreate()
public Cursor query()
public Uri insert()
public int update()
public int delete()
public String getType()
//聲明:
<provider
android:name="xxxxx"
android:authorities="xxxxxxx"
/>
<provider>
音頻/視頻
//構造函數
MediaPlayer player = MediaPlayer.create(this,R.raw.d);
MediaPlayer player = MediaPlayer.create(this,Uri.parse("http://www.asd.comd/a.mp3"));
//注意訪問網絡資源的時候 在manifest.xml中增加權限
//無構造函數
MediaPlayer player = new Mediaplayer();
player.setDataSource("/sdcard/s.wav"); //指定要裝載的音頻文件
player.prepare(); //預加載音頻
/**--------------------------------*/
player.start(); //開始播放
player.stop(); //停止播放
player.pause(); //暫停
/**--------------------------------*/
//編寫play方法
private voidplay(){
try{
player.reset(); //重置MediaPlayer對象
player.setDataSource("xxxxx");
player.prepare();
player.start();
}catch(Exception e){
}
}
SoundPool 也可以來播放音頻
VideoView 播放視頻
<VideoView>
</VideoView>
一般VideoView和MediaController 共同使用
MediaController mc=new MediaController(MainActivity.this);
video.setVideoPath("xxxx");
video.setMediaController(mc);
video.requestFocus();
vidoe.start();
vidoe.pause();
vidoe.stop();
MediaPlayer和SurfaceView播放視頻
<SurfaceView
android:id="@+id/surfaceView1"
android:keepScreenOn="true" //制定播放視頻時,是否打開了屏幕
/>
//播放
private Mediaplayer mp; //聲明MediaPlayer
private SurfaceView sv; //聲明SurfaceView
mp=new Mediaplayer();
sv=(SurfaceView)findViewById(R.id.surfaceView1)
mp.reset();
mp.setDataSource("xxxx");
mp.setDisplay(sv.getHolder());
mp.preare();
mp.start();
mp.stop();
mp.pause();
繪圖
Paint (畫筆)
Paint paint=new Paint(); //無參構造
setColor(int color) color參數可以用Color類提供的常量,也可以用Color.rgb(r,g,b) //0~255
setStrokeWidth(float width) //設置筆的粗細
setStyle(Panit.Cap cap) //設置空心還是實心
參數見下:
//Paint.Style.FILL:填充內部
//Paint.Style.FILL_AND_STROKE :填充內部和描邊
//Paint.Style.STROKE :描邊
Canvas (畫布)
Android中要繪圖,首先要創建一個繼承子View類的視圖,然后在該類中重寫onDraw(Canvas canvas)方法
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
Paint paint=new Paint();
paint.setColor(Color.RED);
canvas.drawRect(40,40,200,100,paint)
}
//canvas 提供的繪制幾何圖形
canvas.drawCircle(cx,cy,radius,paint); //圓形
canvas.drawLine(startX,startY,stopX,stopY,paint); //線
canvas.drawPoint(x,y,paint); //點
canvas.drawRect(left,top,right,bottom,paint); //矩形 這里的left是指左邊離屏幕邊界的距離
常見UI控件
-
文本框:
<TextView android:id="@+id/textview1" android:textSize="20px" //px,pt,sp,in android:textColor="#f00" > </TextView> TextView textView = (TextView) findViewById(R.id.textview1); textView.setBackgroundResource(R.drawable.bg); //設置背景圖片 textView.setBackgroundColor(Color.RED); //設置背景顏色
-
編輯框
EditText類是TextView類的子類<EditText android:inputType="textPassword" //限制為密碼 > </EditText>
getText()方法可獲得編輯框的值
-
按鈕
<Button android:id="@+id/button1" android:text="TEST" > </Button> // 1. onCreate()方法中增加監聽 Button b = (Button)findViewById(R.id.button1); b.setOnClickLinstener(new OnClickListen(){ @Override public void onClick(View v){ //code here } }) // 2. xml中綁定 public void myClick(View v){ //code here } //然后在布局文件中 通過android:onClick="myClick"
-
單選/復選框
//單選框(一般和RadioGroup一同使用) <RadioGroup> <RadioButton android:checked="true|false" //選中狀態 > </RadioButton> </RadioGroup> //isChecked() 用于判斷是否被選中 //復選框 <CheckBox />
-
圖像視圖
<ImageView android:src="@drawable/flower" //圖片于drawbale中的地址 android:scaleType="matrix|fitXY|fitStart|fitCenter|fitEnd|center|centerCrop|centerInside" > </ImageView> //matrix方式縮放,fitXY橫縱縮放,fitStart縮放左上角,fitCenter到中央,fitEnd 到右下角 // center 中央不縮放,centerCrop縮放圖片完全覆蓋imageview,centerInside縮放imageview能完全顯示
-
列表視圖
<ListView android:id="@+id/listView1" android:entries="@array/ctype" > </ListView> //1. 在res\values 目錄創建 arrays.xml <resources> <string-array name="ctype"> <item>1</item> <item>2</item> <item>3</item> </string-array> </resources> //2. 使用關聯適配器 在onCreate() final ListView lv=(ListView)findViewById(R.id.listView1); lv.addHeaderView(line()); //設置header view ArrayAdapter<CharSequence> adapter =ArrayAdapter.createFromResource( this,R.array.ctype,android.R.layout.simple_list_item_check ) lv.setAdapter(adapter); lv.addFooterView(line());
...后續繼續更新適配器
-
拖動條
<SeekBar android:id="@+id/sb1" android:progress="50" //拖動條進度 > </SeekBar> seekbar=(SeekBar)findViewById(R.id.sb1); seekbar.setOnSeekBarChangeListener(new OnSeekChangeListener(){ @Override public void onStopTrackingTouch(SeekBar sb){ //stop seek } @Override public void onStartTrackingTouch(SeekBar sb){ //start seek } @Override public void onProgressChanged(SeekBar sb,int progress,boolean fromUser){ //change seek } })
物理按鍵
KEYCODE_POWER //電源鍵
KEYCODE_BACK //后退鍵
KEYCODE_MENU //菜單
KEYCODE_HOME //home鍵
KEYCODE_SEARCH //查找
KEYCODE_CAMREA //相機
KEYCODE_DPAD_CENTER/UP/DOWN/RIGHT/CENTER //方向鍵
KEYCODE_POWER_VOLMUE_UP|DOWN //音量大小
KEYCODE_POWER_0~9/A~Z //0~9 A~Z
重寫一下回調方法
onKeyUp()
onKeyDown()
onKeyLongPress()
相關監聽事件
onClickListener() 短時間點擊
onLongClickListener() 長時間點擊
關于觸摸:
//實現接口
implements OnTouchListener(){
}
//重寫
onTouch(){
}
實驗
1. 小球跟隨 核心代碼
public class MainActivity extends AppCompatActivity {
private float x=100;
private float y=100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout rl=(RelativeLayout)findViewById(R.id.activity_main);
rl.addView(new myView(this));
}
public class myView extends View{
public myView(Context context){
super(context);
}//構造函數
@Override
protected void onDraw(Canvas canvas){
Paint paint=new Paint();
paint.setColor(Color.RED);
canvas.drawCircle(x,y,50,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
x=event.getX();
y=event.getY();
invalidate();
return true;
}
return super.onTouchEvent(event);
}
}
}
2. 微信登陸(Activity傳值版)
2.1 布局xml (老師的,但是布局中no與name的順序反了) xml 大概看一哈了解一哈就行了
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.intentdemo.MainActivity" >
<TextView
android:id="@+id/textView_no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:layout_alignParentTop="true"
android:layout_marginTop="75dp"
android:text="學號" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/editText1"
android:layout_alignLeft="@+id/editText1"
android:text="姓名" />
<EditText
android:id="@+id/editText_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/textView_no"
android:layout_alignParentRight="true"
android:layout_marginRight="26dp"
android:ems="10" />
<Button
android:id="@+id/button_logon"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editText_name"
android:layout_centerHorizontal="true"
android:layout_marginTop="56dp"
android:text="登陸" />
<EditText
android:id="@+id/EditText_no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText_name"
android:layout_alignTop="@+id/textView2"
android:ems="10" >
<requestFocus />
</EditText>
</RelativeLayout>
2.2 MainActivity (登陸 Activity相互傳遞)
public class MainActivity extends AppCompatActivity {
EditText _name;
EditText _no;
private int CODE=0X111; //自己定義的狀態碼 Activity回傳的時候使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_name=(EditText)findViewById(R.id.editText_name);
_no=(EditText)findViewById(R.id.EditText_no);
findViewById(R.id.button_logon).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name=_name.getText().toString();
String no=_no.getText().toString();
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
//傳值有2種 bundel 或者直接intent ,我這里使用的是bundle 備注的部分則是intent
//intent.putExtra("name",name);
//intent.putExtra("no",no);
Bundle bundle=new Bundle();
bundle.putCharSequence("name",name);
bundle.putCharSequence("no",no);
intent.putExtras(bundle);
startActivityForResult(intent,CODE);
}
});
}
// 自己加的 Activity回傳參數執行函數的代碼部分
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
super.onActivityResult(requestCode,resultCode,data);
if(requestCode==CODE && resultCode==CODE){
Bundle b2=data.getExtras();
Log.d("name",b2.getString("test"));
}
}
}
2.3 Main2Activity (Activity相關回傳參數的代碼 )
public class Main2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView t1=(TextView)findViewById(R.id.v1);
TextView t2=(TextView)findViewById(R.id.v2);
final Intent intent=getIntent();
final Bundle bundle=intent.getExtras();
t1.setText(bundle.getString("name").toString());
t2.setText(bundle.getString("no").toString());
// 如果使用的是intent直接傳值,則用下面方法獲取
// t1.setText(intent.getStringExtra("name"));
// t2.setText(intent.getStringExtra("no"));
findViewById(R.id.back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent t1=new Intent();
Bundle b2=new Bundle();
b2.putCharSequence("test","123131231");
t1.putExtras(b2);
setResult(0X111,t1);
finish();
}
});
}
}
3. 微信登陸(HTTP版)
3.1 MainActivity (登陸HTTP,老師作業的更改版(只有部分核心代碼))
public class MainActivity extends Activity {
EditText _name;
EditText _no;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_name = (EditText) findViewById(R.id.editText_name);
_no = (EditText) findViewById(R.id.EditText_no);
findViewById(R.id.button_logon).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String nameString = _name.getText().toString();
String noString = _no.getText().toString();
String content = "username=" + nameString + "&no=" + noString;
MyNetClient mn = new MyNetClient();
try {
String result = "";
result = mn.HttpPost("http://47.93.13.69/login/login.php", content);
if (!result.equals("")) { //這里是判斷是我自己隨便加的,獲取到result具體如何判斷應該根據實際條件來
Intent intent = new Intent(MainActivity.this, Act1.class);
startActivity(intent);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
3.2 上文用到的老師寫MyNetClient 的HttpPost方法
//普通post提交
//url 提交的頁面
//content 提交的數據,格式:name1=value1&name2=value2...
public static String HttpPost(String url, String content) throws IOException {
HttpURLConnection conn = null;
// 創建一個URL對象
URL mURL = new URL(url);
// 調用URL的openConnection()方法,獲取HttpURLConnection對象
conn = (HttpURLConnection) mURL.openConnection();
conn.setRequestMethod("POST");// 設置請求方法為post
conn.setDoOutput(true);// 設置此方法,允許向服務器輸出內容
conn.setDoInput(true);
conn.setUseCaches(false);
conn.connect(); //打開連接
// post請求的參數
String data = content;
// 獲得一個輸出流,向服務器寫數據,默認情況下,系統不允許向服務器輸出內容
OutputStream out = conn.getOutputStream();// 獲得一個輸出流,向服務器寫數據
out.write(data.getBytes());
out.flush();
out.close();
String responseCookie = conn.getHeaderField("Set-Cookie");
if (responseCookie != null) {
Log.i("demo", responseCookie);
}
int responseCode = conn.getResponseCode();// 調用此方法就不必再使用conn.connect()方法
if (responseCode == 200) {
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String result = br.readLine();
return result;
}
return null;
}
臨時抱佛腳的復習資料,可能存在一些問題。如有問題,請在評論區指出,謝謝。