Android基礎(chǔ)

Android基礎(chǔ)

Android系統(tǒng)架構(gòu)

JNI java native interface

1. application:應用層, java
2. application framework: 應用框架層, java + JNI
3. libraries 和 dalvik:函數(shù)庫和虛擬機層, c/c++ 
4. linux kernel: linux 內(nèi)核驅(qū)動層, c

JVM和DVM的不同

區(qū)別

  1. 基于的架構(gòu)不同偏窝。jvm 基于棧架構(gòu)衬吆,棧是位于內(nèi)存上的一個空間梁钾,執(zhí)行指令操作,需要向cpu尋址逊抡; dvm 基于寄存器架構(gòu)姆泻,寄存器是cpu的一個組成部分,執(zhí)行指令操作無需尋址直接執(zhí)行冒嫡。
  2. 執(zhí)行文件的格式不同拇勃,jvm執(zhí)行的是多個.class文件。 dvm執(zhí)行的是一個.dex文件孝凌。

art 模式 (android runtime)

雖占用空間略大方咆,但運行速度更快。

在Android 4.4以前蟀架,安卓手機系統(tǒng)的應用程序均在Dalvik Java的虛擬機上運行瓣赂,這種運行模式是還要依靠一個編譯器來實現(xiàn)與應用程序的溝通。應程序每次運行時片拍,都需要將程序內(nèi)的代碼轉(zhuǎn)變?yōu)闄C器碼才能運行钩述,這無形中多附加了一道手續(xù),這就造成了耗電相對較快穆碎、占用內(nèi)存大的問題牙勘。

art: 程序在安裝時需要預編譯讀取,將代碼轉(zhuǎn)換為機器碼。

  • 好處:程序運行時方面,無需時時轉(zhuǎn)換放钦,運行速度快 ;
  • 缺點:安裝時間稍長恭金,由于轉(zhuǎn)換機器碼操禀,所以占用略高的存儲空間。

sdk目錄

add-ons:預留的一個附加目錄
build-tools:構(gòu)建工具目錄
docs: 文檔目錄
extras:開發(fā)中額外提供的一些工具比如intelHAXM加速器及jar
platforms: 不同版本android的核心jar包
platforms-tools:平臺一些相關(guān)的工具
sources:源碼
system-images:系統(tǒng)鏡像文件
tools:開發(fā)中使用的一些工具横腿,如9path颓屑,做圖片拉伸適配的。
emulator:模擬器

DDMS(Dalvik Debug Monitor Service)

file explorer: 列出當前設(shè)備所有目錄耿焊。

/data/app:安裝的第三方apk都在此目錄
/system/app: 系統(tǒng)預裝應用apk在此目錄  
/data/data:應用的私有目錄揪惦,系統(tǒng)每安裝一個新的應用程序,都會在此目錄創(chuàng)建該應用包名的文件罗侯,用來存放該應用的私有數(shù)據(jù)器腋,當應用卸載時,該包名的文件夾也會被刪除钩杰。     
/sdcard :外部存儲目錄纫塌,一般會鏈接指向到另一個目錄,用來存放大數(shù)據(jù)讲弄。

Android工程目錄結(jié)構(gòu)

applicationId和package

app下的build.gradle

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.example.hello"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
     <!-- 
    applicationId: 應用程序的包名措左,Android設(shè)備和應用商店上,applicationId是一個android程序的唯一標示
    versionCode:應用程序的版本號 
    versionName:版本(名)描述
    minSdkVersion: 應用最低能安裝的系統(tǒng)版本
    compileSdkVersion:編譯時候的版本避除,始終使用最新版本
    targetSdkVersion解釋起來復雜媳荒,Android 提供向前兼容的主要依據(jù),記住和compileSdkVersion版本號保持一致就好-->

app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hello">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
       <!--  應用程序的入口,進入app的第一個activity
            action : MAIN 主要的
            category : LAUNCHER 啟動 發(fā)射 -->
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

build.gradle下的applicationId v.s. AndroidManifest.xml下的package驹饺。

默認(最好)是兩者保持一致钳枕。

在Android Studio中是兩個獨立的東西,可以修改applicationId赏壹,與packageName不一致也可以的(不推薦)鱼炒。

最簡單的MainActivity

oncreate :是Activity啟動時調(diào)用 , activity 相當于java web中的servlet(處理業(yè)務邏輯)蝌借, layout 相當于java web中的jsp(負責顯示)

package com.example.helloworld;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    //oncreate :是Activity啟動時調(diào)用 昔瞧, activity 相當于java web中的servlet, layout 相當于java web中的jsp
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // savedInstanceState作用是在acticitypause狀態(tài)菩佑,被kill掉之前自晰,保存此時的狀態(tài)。
        // 這樣當activity開始時候調(diào)用onCreat時候就能獲得狀態(tài)數(shù)據(jù)savedInstanceState
        super.onCreate(savedInstanceState);
        //將一個布局文件作為activity的內(nèi)容顯示
        setContentView(R.layout.activity_main);

    }
}

Android的打包過程

.java --(使用jdk)---> .class ---(使用dx.bat)--->.dex(res,assets,androidmanifest.xml)--(使用aapt)-->.apk--(使用jarsigner簽名)--> final apk

ADB指令

ADB (android debug bridge)

建立手機與電腦直接的連接 , adb運行的端口號是5037稍坯。

為方便使用酬荞,需要將環(huán)境變量的配置:\sdk\platform-tools配置到環(huán)境變量搓劫。

1. adb devices :列出當前電腦所連接的android設(shè)備
2. adb push pc_path  phone_path :將電腦端文件放到手機端
3. adb pull phone_paht pc_path :將手機端文件拉到電腦端
4. adb install [-r] apkpath ; 安裝一個電腦端的apk文件。-r可選:強制安裝
5. adb uninstall packagename; 卸載一個應用
//三個指令聯(lián)合使用來解決adb被占用混巧,或斷開連接的情況
6. adb kill-server : 結(jié)束adb服務的鏈接
7. adb start-server :開啟adb服務的鏈接
8. netstat -oan 查看端口: 查看端口
9. adb shell:進入當前設(shè)備linux環(huán)境下
10.adb shell下 ls -l :查看當前設(shè)備的目錄結(jié)構(gòu)
11.adb shell下 logcat :查看系統(tǒng)運行中的日志信息

簡單的例子--撥號

  1. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="請輸入手機號"
        />

    <EditText
        android:id="@+id/tel_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal" />

    <Button
        android:id="@+id/call"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="撥打" />
</LinearLayout>

  1. 主界面
package com.example.hello;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private EditText editText;
    private Intent callIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 獲取布局里面的控件
        editText = (EditText) findViewById(R.id.tel_number);
        Button callButton = (Button) findViewById(R.id.call);

        callButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 用戶可能輸入了空格或者制表符枪向,除去
                String telnumber = editText.getText().toString().trim();
                // ACTION_CALL和ACTION_DIAL的區(qū)別在于,前者直接撥打出去咧党,后者彈出撥號界面和號碼秘蛔,需要用戶手動撥打
                callIntent = new Intent(Intent.ACTION_CALL);
              // "tel:"指定了協(xié)議
                callIntent.setData(Uri.parse("tel:" + telnumber));
              // 動態(tài)申請運行時權(quán)限,傳入的1是一個唯一碼傍衡,沒申請到權(quán)限時不能執(zhí)行后續(xù)動作深员,所以放在else分支里
                if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);
                } else {
                    startActivity(callIntent);
                }
            }
        });
    }
    // requestCode對應上面的唯一碼,這個方法根據(jù)用戶允許或者拒絕來處理
    // PackageManager.PERMISSION_GRANTED表示用戶點擊了允許
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED) {
                  // 用戶允許后立即撥打電話
                    startActivity(callIntent);
                } else {
                    Toast.makeText(MainActivity.this, "你拒絕了權(quán)限蛙埂!", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

記得使用permission.CALL_PHONE時候需要在AndroidManifest.xml里面注冊倦畅。

<uses-permission android:name="android.permission.CALL_PHONE" />

常用的重寫按鈕點擊事件的方法

  1. 上面用的匿名內(nèi)部類的方法,當按鈕多的時候箱残,每一個按鈕就會new出一個類開辟了一片空間滔迈。

  2. 讓當前Activity實現(xiàn)implements View.OnClickListener止吁,對于有多個按鈕時很方便被辑。

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
        private EditText editText;
        private Intent callIntent;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            editText = (EditText) findViewById(R.id.tel_number);
            Button callButton = (Button) findViewById(R.id.call);
         // 當前類就是一個listener
            callButton.setOnClickListener(this);
        }
     // 將撥打電話功能封裝
        private void callPhone() {
            String telnumber = editText.getText().toString().trim();
            callIntent = new Intent(Intent.ACTION_CALL);
            callIntent.setData(Uri.parse("tel:" + telnumber));
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);
            } else {
                startActivity(callIntent);
            }
        }
     // 可能有多個按鈕,通過getId方法來判斷敬惦,id就是布局文件里定義的
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.call:
                    callPhone();
                    break;
                default:
            }
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            switch (requestCode) {
                case 1:
                    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        startActivity(callIntent);
                    } else {
                        Toast.makeText(MainActivity.this, "你拒絕了權(quán)限盼理!", Toast.LENGTH_SHORT).show();
                    }
                    break;
                default:
                    break;
            }
        }
    }
    

by @sunhaiyu

2017.4.7

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市俄删,隨后出現(xiàn)的幾起案子宏怔,更是在濱河造成了極大的恐慌,老刑警劉巖畴椰,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臊诊,死亡現(xiàn)場離奇詭異,居然都是意外死亡斜脂,警方通過查閱死者的電腦和手機抓艳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帚戳,“玉大人玷或,你說我怎么就攤上這事∑危” “怎么了偏友?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長对供。 經(jīng)常有香客問我位他,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任棱诱,我火速辦了婚禮泼橘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迈勋。我一直安慰自己炬灭,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布靡菇。 她就那樣靜靜地躺著重归,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厦凤。 梳的紋絲不亂的頭發(fā)上鼻吮,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音较鼓,去河邊找鬼椎木。 笑死,一個胖子當著我的面吹牛博烂,可吹牛的內(nèi)容都是我干的香椎。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼禽篱,長吁一口氣:“原來是場噩夢啊……” “哼畜伐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起躺率,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤玛界,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悼吱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慎框,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年后添,在試婚紗的時候發(fā)現(xiàn)自己被綠了笨枯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡吕朵,死狀恐怖猎醇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情努溃,我是刑警寧澤硫嘶,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站梧税,受9級特大地震影響沦疾,放射性物質(zhì)發(fā)生泄漏称近。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一哮塞、第九天 我趴在偏房一處隱蔽的房頂上張望刨秆。 院中可真熱鬧,春花似錦忆畅、人聲如沸衡未。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缓醋。三九已至,卻和暖如春绊诲,著一層夾襖步出監(jiān)牢的瞬間送粱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工掂之, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抗俄,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓世舰,卻偏偏與公主長得像动雹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子冯乘,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容