1. 程式人生 > >Android APK打包安裝、應用程序啟動過程、Activity啟動流程

Android APK打包安裝、應用程序啟動過程、Activity啟動流程

目錄

一、Android APK的構建過程

通過IDE可以生成可以在android裝置中安裝的apk檔案,Google官方提供的構建APK的過程流程圖如下:

  • 打包APK流程總結如下:
  1. AAPT(Android Asset Packaging Tool)工具會打包應用中的資原始檔,如AndroidManifest.xml、layout佈局中的xml等,並將xml檔案編譯為二進位制形式,當然assets資料夾中的檔案不會被編譯,圖片及raw資料夾中的資源也會保持原來的形態,需要注意的是raw資料夾中的資源也會生成資源id。AAPT編譯完成之後會生成R.java檔案。
  2. AIDL工具會將所有的aidl介面轉化為java介面。
  3. 所有的java程式碼,包括R.java與aidl檔案都會被Java編譯器編譯成.class檔案。
  4. Dex工具會將上述產生的.class檔案及第三庫及其他.class檔案編譯成.dex檔案(dex檔案是Dalvik虛擬機器可以執行的格式),dex檔案最終會被打包進APK檔案。
  5. ApkBuilder工具會將編譯過的資源及未編譯過的資源(如圖片等)以及.dex檔案打包成APK檔案。
  6. 生成APK檔案後,需要對其簽名才可安裝到裝置,平時測試時會使用debug keystore,當正式釋出應用時必須使用release版的keystore對應用進行簽名。
  7. 如果對APK正式簽名,還需要使用zipalign工具對APK進行對齊操作,這樣做的好處是當應用執行時會提高速度,但是相應的會增加記憶體的開銷。

我們知道,通過Intent就可以執行APK安裝的,執行如下程式碼後,我們就會開啟安裝apk檔案的程式並執行安裝邏輯了,大家應該都知道這段程式碼執行的結果是開啟一個隱式的Activity,即PackageInstallerActivity。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + path),"application/vnd.android.package-archive");
context.startActivity(intent);
  • 安裝APK流程總結如下:
  1. 程式碼中執行intent.setDataAndType(Uri.parse(“file://” + path),”application/vnd.android.package-archive”);可以開啟隱士的PackageInstallerActivity。
  2. PackageInstallerActivity主要用於執行解析apk檔案;解析manifest.xml、解析簽名等操作。
  3. 點選安裝按鈕,調起InstallAppProcess,這個Activity主要用於執行安裝apk邏輯,用於初始化安裝介面,用於初始化使用者UI;並呼叫PackageInstaller執行安裝邏輯。
  4. InstallAppProcess內註冊有廣播,當安裝完成之後接收廣播,更新UI。顯示apk安裝完成介面。

二、Android 應用程序啟動過程

    首先,Android在系統架構分為四個層面。從高層到低層分別是應用程式層、應用程式框架層、系統執行庫層和linux核心層。另外,程序是系統的執行單位。Linux系統是核心底層,那麼Android的其他程序都是基於Linux程序的根程序init程序,因此它可以算作是整個android作業系統的第一個程序。最後,我們知道android系統的Zygote程序是所有的android程序的父程序,包括SystemServer和各種應用程序都是通過Zygote程序fork出來的。而Zygote程序則是通過linux系統的init程序啟動的,也就是說,android系統中各種程序的啟動方式及順序是:

init程序 –> Zygote程序 –> SystemServer程序 –>各種應用程序

各種應用程序:啟動自己編寫的客戶端應用時,一般都是重新啟動一個應用程序,有自己的虛擬機器與執行環境;

init程序在啟動Zygote程序時一般都會呼叫ZygoteInit類的main方法,Zygote程序mian方法主要執行邏輯:

  • 初始化DDMS;

  • 註冊Zygote程序的socket通訊;

  • 初始化Zygote中的各種類,資原始檔,OpenGL,類庫,Text資源等等;

  • 初始化完成之後fork出SystemServer程序;

  • fork出SystemServer程序之後,關閉socket連線;

其實,SystemServer程序主要的作用是啟動各種系統服務,比如ActivityManagerService,PackageManagerService,WindowManagerService等服務。我們平時熟知的各種系統性的服務其實都是在SystemServer程序中啟動的,而當我們的應用需要使用各種系統服務的時候,其實也是通過與SystemServer程序通訊獲取各種服務物件的控制代碼來執行相應的操作。

  • SystemServer程序啟動服務的啟動函式為main函式;

  • SystemServer在執行過程中首先會初始化一些系統變數,載入類庫,建立Context物件,建立SystemServiceManager物件等之後才開始啟動系統服務;

  • SystemServer程序將系統服務分為三類:boot服務,core服務和other服務,並逐步啟動;

  • SystemServer程序在嘗試啟動服務之前會首先嚐試與Zygote建立socket通訊,只有通訊成功之後才會開始嘗試啟動服務;

  • 建立的系統服務過程中主要通過SystemServiceManager物件來管理,通過呼叫服務物件的構造方法和onStart方法初始化服務的相關變數;

  • 服務物件都有自己的非同步訊息物件,並執行在單獨的執行緒中;

其實,我們知道SystemServer程序主要用於啟動系統的各種服務,而且其中就包含負責啟動Launcher程式的服務-LauncherAppService。Launcher 程式就是我們平時看到的桌面程式,它其實也是一個android應用程式,只不過這個應用程式是系統預設第一個啟動的應用程式,這裡我們就簡單的分析一下Launcher應用的啟動流程。

前面說SystemServer呼叫三個內部方法分別啟動boot service、core service和other service。在呼叫startOtherService方法中就會通過呼叫mActivityManagerService.systemReady()方法。

public void systemReady(final Runnable goingCallback) {
        ...
        // Start up initial activity.
        mBooting = true;
        startHomeActivityLocked(mCurrentUserId, "systemReady");
        ...
    }

這個方法體中呼叫了startHomeActivityLocked方法,看名字就知道開始執行啟動homeActivity的操作。好了,既然如此,我們再看一下startHomeActivityLocked的具體實現:

boolean startHomeActivityLocked(int userId, String reason) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            return false;
        }
        Intent intent = getHomeIntent();//下面第一段程式碼進入檢視
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);//第二段程式碼檢視
            }
        }

        return true;
    }
Intent getHomeIntent() {
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

可以發現,Intent是一個隱士物件,並且添加了Intent.CATEGORY_HOME常量,這個其實是一個launcher的標誌,一般系統的啟動頁面Activity都會在androidmanifest.xml中配置這個標誌。

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
        startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
                null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
                null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
                null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
                0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
                false /* componentSpecified */,
                null /* outActivity */, null /* container */,  null /* inTask */);
        if (inResumeTopActivity) {

            scheduleResumeTopActivities();

        }
    }

發現其呼叫的是scheduleResumeTopActivities()方法,這個方法其實是關於Activity的啟動流程的邏輯的,這邏輯後面會講。因為我們的Launcher啟動的Intent是一個隱士的Intent,所以我們會啟動在androidmanifest.xml中配置了相同catogory的activity,androidManifest中配置的這個catogory其實就是LauncherActivity。

LauncherActivity繼承與ListActivity,我們先看一下其Layout佈局檔案和onCreate方法:

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

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <TextView
        android:id="@android:id/empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/activity_list_empty"
        android:visibility="gone"
        android:textAppearance="?android:attr/textAppearanceMedium"
        />

</FrameLayout>
@Override
protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        mPackageManager = getPackageManager();
        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
            requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
            setProgressBarIndeterminateVisibility(true);
        }
        onSetContentView();
        mIconResizer = new IconResizer();

        mIntent = new Intent(getTargetIntent());
        mIntent.setComponent(null);
        mAdapter = new ActivityAdapter(mIconResizer);

        setListAdapter(mAdapter);
        getListView().setTextFilterEnabled(true);

        updateAlertTitle();
        updateButtonText();

        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
            setProgressBarIndeterminateVisibility(false);
        }
    }

可見,手機桌面其實就是一個ListView控制元件,在onCreate方法中初始化了一個PackageManager,從中查詢出系統所有已經安裝的應用列表,包括應用包名、圖示等資訊,然後將這些資訊以Adapter方式注入到Listview中將系統應用圖示和名稱顯示出來。 另外,在系統的回撥方法onListItemClick中說明了,為什麼我們點選某一個應用圖示之後就可以啟動某一項應用的原因了。

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
}
protected Intent intentForPosition(int position) {
        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
        return adapter.intentForPosition(position);
}
public Intent intentForPosition(int position) {
            if (mActivitiesList == null) {
                return null;
            }

            Intent intent = new Intent(mIntent);
            ListItem item = mActivitiesList.get(position);
            intent.setClassName(item.packageName, item.className);
            if (item.extras != null) {
                intent.putExtras(item.extras);
            }
            return intent;
}

    所以,LauncherActivity中是以ListView來顯示我們的應用圖示列表的,並且為每個Item儲存了應用的包名和啟動Activity類名,這樣點選某一項應用圖示的時候就可以根據應用包名和啟動Activity名稱啟動我們的App了。

    其實Android中應用程序可以通過許多方式啟動,比如啟動一個Activity、Service、ContentProvider或BroadcastReceiver,也就是說通過啟動四大元件的方式啟動,這時候系統會判斷當前這些元件所需要的應用程序是否已經啟動,若沒有的話,則會啟動應用程序。通過上面Launcher啟動流程,我們知道每一個launcher中的圖示對應著一個應用報名和啟動activity類名,檢視LauncherActivity中的圖示點選事件:

protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
}

這裡呼叫了startActivity方法傳入Intentd物件來啟動這個activity。很明顯,當前該應用屬於冷啟動,也就是說我們呼叫的startActivity方法不單單為我們啟動了這個activity,也同時在啟動activity之前啟動了這個應用程序。好了,那我們這裡就以這個方法為入口分析一下應用程序的啟動流程。

@Override
public void startActivity(Intent intent) {
        this.startActivity(intent, null);
}

發現其呼叫的startActivity的過載方法,傳入Intent物件和可為空Bundle物件。 並且發現繼續呼叫startActivityForResult方法。

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            startActivityForResult(intent, -1);
        }
    }

很明顯的此時傳遞的options為空,繼續跟進:

public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
}

好吧,最後呼叫的還是startActivityForResult(intent, requestCode, null)這個過載方法:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
       
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

首先注意mInstrumentation.execStartActivity方法。Instrumentation物件,他是Android系統中應用程式端操作Activity的具體操作類,這裡的操作是相對於ActivityManagerService服務端來說的。也就是說當我們在執行對Activity的具體操作時,比如回撥生命週期的各個方法都是藉助於Instrumentation類來實現的。看一下原始碼:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
//關鍵程式碼
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

關鍵程式碼段實際上是程序間通訊。ActivityManagerNative繼承於Binder介面,本身就是一個Binder物件,然後上面我們介紹SystemServer程序的時候對ActivityManagerService有過了解,發現其繼承於ActivityManagerNative,好吧,瞭解過Binder機制的知道,ActivityManagerService就是這個Binder機制的伺服器端而ActivityManagerNative就是這個Binder機制的客戶端。所以我們這裡呼叫的startActivity實際上是將引數傳遞給ActivityManagerService,並執行ActivityManagerService的startActivity方法。

既然這樣,我們看一下ActivityManagerService的startActivity方法:

@Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

然後我們繼續看一下startActivityAsUser方法:

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);

        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

繼續檢視startActivityMayWait方法:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        ...

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);

            ...

            return res;
        }
    }

這裡呼叫了startActivityLocked方法,也就是說在初始化其他邏輯之後,這個方法會呼叫startActivityLocked方法,然後我們檢視startActivityLocked方法發現其呼叫了resumeTopActivitiesLocked方法:

if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}

繼續跟進:

final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }

resumeTopActivityLocked方法中又呼叫了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法中又呼叫了startSpecificActivityLocked方法:

final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

檢視startProcessLocked方法的具體實現:

checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");

檢視關鍵程式碼,這裡呼叫了Process.start方法:

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

最後,這裡的processClass就是要啟動的程序的名稱,這裡傳遞的就是ActivityThread:"android.app.ActivityThread"。具體的Process啟動程序的Native層程式碼這裡不做過多的分析,這個方法就是啟動了AcitivtyThread程序並執行了ActivityThread的main方法,所以我們經常說的程序的啟動方法就是ActivityThread的main方法,就在這裡實現的。

三、 Android Activity的啟動流程

  • Activity的啟動流程一般是通過呼叫startActivity或者是startActivityForResult來開始的

  • startActivity內部也是通過呼叫startActivityForResult來啟動Activity,只不過傳遞的requestCode小於0

  • Activity的啟動流程涉及到多個程序之間的通訊這裡主要是ActivityThread與ActivityManagerService之間的通訊

  • ActivityThread向ActivityManagerService傳遞程序間訊息通過ActivityManagerNative,ActivityManagerService向ActivityThread程序間傳遞訊息通過IApplicationThread。

  • ActivityManagerService接收到應用程序建立Activity的請求之後會執行初始化操作,解析啟動模式,儲存請求資訊等一系列操作。

  • ActivityManagerService儲存完請求資訊之後會將當前系統棧頂的Activity執行onPause操作,並且IApplication程序間通訊告訴應用程式繼承執行當前棧頂的Activity的onPause方法;

  • ActivityThread接收到SystemServer的訊息之後會統一交個自身定義的Handler物件處理分發;

  • ActivityThread執行完棧頂的Activity的onPause方法之後會通過ActivityManagerNative執行程序間通訊告訴ActivityManagerService,棧頂Actiity已經執行完成onPause方法,繼續執行後續操作;

  • ActivityManagerService會繼續執行啟動Activity的邏輯,這時候會判斷需要啟動的Activity所屬的應用程序是否已經啟動,若沒有啟動則首先會啟動這個Activity的應用程式程序;

  • ActivityManagerService會通過socket與Zygote繼承通訊,並告知Zygote程序fork出一個新的應用程式程序,然後執行ActivityThread的mani方法;

  • 在ActivityThead.main方法中執行初始化操作,初始化主執行緒非同步訊息,然後通知ActivityManagerService執行程序初始化操作;

  • ActivityManagerService會在執行初始化操作的同時檢測當前程序是否有需要建立的Activity物件,若有的話,則執行建立操作;

  • ActivityManagerService將執行建立Activity的通知告知ActivityThread,然後通過反射機制創建出Activity物件,並執行Activity的onCreate方法,onStart方法,onResume方法;

  • ActivityThread執行完成onResume方法之後告知ActivityManagerService onResume執行完成,開始執行棧頂Activity的onStop方法;

  • ActivityManagerService開始執行棧頂的onStop方法並告知ActivityThread;

  • ActivityThread執行真正的onStop方法;

相關推薦

Android APK打包安裝應用程序啟動過程Activity啟動流程

目錄 一、Android APK的構建過程 通過IDE可以生成可以在android裝置中安裝的apk檔案,Google官方提供的構建APK的過程流程圖如下: 打包APK流程總結如下: AAPT(Android Asset Packaging Tool)工

WEB服務器應用程序服務器HTTP服務器區別

一個 到你 文章 配置 通過 http ring fun 內容   WEB服務器、應用程序服務器、HTTP服務器有何區別?IIS、Apache、Tomcat、Weblogic、WebSphere都各屬於哪種服務器,這些問題困惑了很久,今天終於梳理清楚了: Web服務

IIS連接數IIS並發連接數IIS最大並發工作線程數應用程序池的隊列長度

這就是 規範性 初級 展示 約會 第一次 數量 企業 通用 關於並發你真的了解嗎?(一) 前言:對於很多工作時間短或者編程經驗不足的程序員來說,大多數會覺得並發這個詞離自己太遙遠,之所以知道並發也不過是因為受那些技術大佬成天討論並發等問題耳濡目染罷了。更有甚者,一些

應用程序添加到開機啟動

sof 方法 soft start 打開 個人 windows 快捷 運行 1.創建應用程序的快捷方式2.打開目錄C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp3.將應用程序的快捷方式復制到該目錄下

使用RPM包工具和源碼包編譯安裝Linux應用程序

linux rpm 軟件包安裝 楊書凡 源碼包編譯安裝 系統命令:一般在/bin和/sbin目錄中,或為Shell內部指令,完成對系統的基本管理工作,例如IP配置工具應用程序:通常在/usr/bin和/usr/sbin目錄中,完成相對獨立的其他輔助任務,例如網頁瀏覽器Linux應用程序的組

C#:進程線程應用程序域(AppDomain)與上下文分析

gpo 驗證 執行上下文 結束 take 名稱 了解 不同 代理 進程 進程是操作系統用於隔離眾多正在運行的應用程序的機制。在.Net之前,每一個應用程序被加載到單獨的進程中,並為該進程指定私有的虛擬內存。進程不能直接訪問物理內存,操作系統通過其它的處理把這些虛擬內

關於進程線程應用程序域(AppDomain)

對象 關系 程序集 狀態 控制流程 邊界 創建 控制流 機制 什麽是進程?什麽是線程?什麽是應用程序集?及三者之間的關系(以下做一些簡單的概念性的理解) 三者共同的基礎對象!!!——應用程序 1、進程是操作系統用於隔離眾多正在運行的應用程序的機制,進程的缺點是降低了性能。

進程應用程序域與上下文之間的關系

rom 靜態方法 pdo main.c 17. 生命周期 狀態 ons gate 使用.NET建立的可執行程序 *.exe,並沒有直接承載到進程當中,而是承載到應用程序域(AppDomain)當中。應用程序域是.NET引入的一個新概念,它比進程所占用的資源要少,可以

Linux應用程序基礎 1應用程序與系統命令的關系 文件位置 主要用途

soft sock efi 地址欄 -h sha 包安裝 文檔 -a 一、Linux應用程序基礎1、應用程序與系統命令的關系文件位置主要用途使用環境運行格式2、Linxu下軟件包的類型rpmdeb源代碼包自帶安裝程序的軟件包免安裝的軟件包 二、使用RPM包管理工具1、RPM

Android判斷是否安裝某個應用

在程式碼中判斷: 一、可以通過獲取某個應用資訊並捕獲未安裝時的異常判斷: private boolean checkAppInstalled(Context context,String pkgName) { if (pkgName== null || pkgName.isE

Android apk打包命名規則

摘要:前言在日常的開發過程中,許多剛入行的開發者在apk打包命名、應用迭代版本的檔案留存管理上都比較混亂——產生這些問題的原因無外乎以下兩種:一是之前沒有相關的操作經驗、頭尾不能兼顧;一是公司沒有制定對應的規範、無有效參照範例。當然,所謂的規範在業內不會存在唯一的標準與格式(對於規範的理解,

安全程式設計之Android APK打包程式碼混淆

第一步:在專案工程目錄下的proguard-rules.pro檔案中配置自定義的混淆規則 #注意: #1.引用外部的jar包 如果不是自己寫的最好不混淆它們,因為外部jar包有可能已經混淆過 #2.不要混淆XML佈局中使用的自定義控制元件類,混淆後加載佈局會報找不到該控制

(轉)android Apk打包過程概述_android是如何打包apk

最近看了老羅分析android資源管理和apk打包流程的部落格,參考其他一些資料,做了一下整理,脫離繁瑣的打包細節和資料結構,從整體上概述了apk打包的整個流程。 流程概述: 1、打包資原始檔,生成R.java檔案 2、處理aidl檔案,生成相應java

Android APK安裝

       簡述下APK的安裝過程,在文章的正式開始之前,我們需要做一些知識的補充 1:如何呼叫起安裝介面,以從sd卡安裝為例子 Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); in

android apk靜默安裝和解除安裝(2)

String pkgName = mPkgInfo.packageName; //得到包名 String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName }); if (oldName != null &&

Android APK打包流程

概述 今天主要講一下Android程式的生成步驟,即Android打包成APK的流程。 通常情況下,在開發過程中打包APK是一件很簡單的事,主要可以通過兩種方式:一種是用Eclipse或者Android Studio整合開發環境直接生成APK;另一種是使用Ant\Gl

Android Apk打包原理

打包資原始檔,生成R.java檔案 打包資原始檔的工具是aapt(The Android Asset Packing Tool),位於android-sdk/platform-tools目錄下。 在這個過程中,專案中的AndroidManifest.xml檔案和佈局檔案xml都會編譯生成相應的R.ja

android】sdk安裝及環境變量配置android stdio的安裝及新建項目

工程 end tps 發現 tool 版本 不知道 php work (前提,安裝配置好jdk) 首先下載一個sdk(http://tools.android-studio.org/index.php/sdk) 我先下的是.exe版本,因為後面括號Recommend,

android Apk打包過程概述_android是如何打包apk

最近看了老羅分析android資源管理和apk打包流程的部落格,參考其他一些資料,做了一下整理,脫離繁瑣的打包細節和資料結構,從整體上概述了apk打包的整個流程。流程概述:1、打包資原始檔,生成R.java檔案2、處理aidl檔案,生成相應java 檔案3、編譯工程原始碼,生成相應class 檔案4、轉換所有

Android Apk靜默安裝的方法(後臺安裝

最近跟第三方一個廠家合作,我們這邊有需求讓他們給我們提供應用靜默安裝的方法(也就是不顯示介面的後臺安裝)結果垃圾公司又各種介面說做不了,一直拖延時間沒辦法只能我們自己想辦法做,這幾天我也研究了下終於有結果了,下面我把我的方法發出來。一、大概說下思路(1)利用系統應用的許可權執