- Các ứng dụng Android được viết bởi ngôn ngữ JAVA. Mã Java đã được biên dịch cùng với các dữ liệu và các file tài nguyên được yêu cầu bởi ứng dụng được đóng gói bởi tool aapt trong Android package, một file archive .apk. File này được sử dụng để phân phối các ứng dụng và cài đặt nó lên thiết bị, nó là file mà người dùng download nó vào ứng dụng. Tất cả code trong một file .apk được xem là một ứng dụng.
- Theo mặc định, mỗi ứng dụng Android chạy trên tiến trình Linux của chính nó. Android bắt đầu tiến trình khi code của ứng dụng cần được thực thi và kết thúc tiến trình khi nó không còn cần thiết và các tài nguyên của ứng dụng được yêu cầu bởi các ứng dụng khác.
- Mỗi một tiến trình đều có một máy ảo VM của riêng nó, vì vậy code của mỗi ứng dụng chạy độc lập với các ứng dụng khác.
- Theo mặc định, mỗi ứng dụng được chỉ định một ID người dùng Linux duy nhất. Permission được thiết lập để các file của ứng dụng chỉ hiển thị cho người dùng đó và chỉ cho ứng dụng đó - mặc dù có nhiều cách để export chúng vào các ứng dụng khác.
Có thể sắp xếp cho hai ứng dụng chia sẻ cùng một ID người dùng, trong trường hợp chúng có thể xem các file của nhau. Để tiết kiệm tài nguyên hệ thống, các ứng dụng với cùng một ID cũng có thể sắp xếp để chạy trong cùng tiến trình Linux, chia sẻ cùng một máy ảo.
Application Fundamentals |
Nội dung [ Bài 2] Application Fundamentals - Application Components
I. Application Components
- Activity
- Services
- Broadcast Receivers
- Content Providers
- Activating components: intents
- Shutting down components
- The manifest file
- Intent filters
I. Application Components
- Một tính năng nổi bật của Android là một ứng dụng có thể sử dụng các thành phần của các ứng dụng khác. Ví dụ, nếu ứng dụng của bạn cần hình thị một danh sách các image, và các ứng dụng khác đã phát triển danh sách này phù hợp với yêu cầu của bạn, thì bạn chỉ cần gọi nó lên để sử dụng thay vì phát triển lại. Ứng dụng của bạn không kết hợp mã nguồn của ứng dụng khác hay liên kết với nó, thay vào đó nó chỉ đơn giãn start một mẫu của các ứng dụng khác khi nhu cầu phát sinh.
- Đối làm được điều này, hệ thống phải có khả năng start một tiến trình ứng dụng khi bất kỳ thành phần nào của nó cần thiết, và khởi tạo các đối tượng Java cho thành phần đó. Vì vậy, không giống như các ứng dụng trên các hệ thống khác, các ứng dụng Android không có một entry point duy nhất cho ứng dụng (chẳng hạn như không có phương thức main()). Thay vào đó, chúng có các thành phần mà hệ thống có thể khởi tạo và chạy khi cần thiết. Có bốn loại thành phần:
1. Activity
- Một Activity đại diện cho một giao diện người dùng trực quan mà người dùng có thể thực hiện. Ví dụ, một Activity có thể là một danh sách các menu item mà người dùng có thể lựa chọn. Một ứng dụng gửi tin nhắn văn bản có thể có một Activity để hiển thị một danh sách các contacts để gửi tin nhắn đến, một Activity thứ hai để viết tin nhắn đến contact đã chọn, và các Activity khác để xem tin nhắn cũ hoặc cài đặt các thay đổi. Mặc dù chúng làm việc cùng nhau để tạo thành một giao diện người dùng gắn kết, nhưng mỗi Activity độc lập với nhau.
- Mỗi Activity có một cửa sổ mặc định để vẽ. Thông thường, cửa sổ này fill đầy màn hình nhưng cũng có thể nhỏ hơn màn hình và nổi lên trên các cửa sổ khác. Một Activity cũng có thể sử dụng các cửa sổ bổ sung - ví dụ, một hộp thoại pop-up được gọi cho một phản ứng người dùng, hoặc một cửa sổ mà trình bày cho users thông tin quan trọng khi lựa chọn một mục cụ thể trên màn hình.
- Các nội dung trực quan của cửa sổ được cung cấp bởi một hệ thống các views – các đối tượng xuất phát từ lớp cơ sở View. Mỗi view kiểm soát một không gian hình chữ nhật cụ thể trong cửa sổ. Các view cha sẽ bố trí layout cho các phần tử con của nó. View là nơi mà hoạt động tương tác với người dùng diễn ra.
- Để đưa một View vào cửa sổ của Acitivity, gọi phương thức Acitivity.setContentView().
2. Services
- Một Service không có một giao diện người dùng trực quan, mà nó chạy background trong một khoản thời gian không xác định. Ví dụ, một Service có thể chơi nhạc nền khi người dùng tham dự vào các vấn đề khác, hoặc nó có thể lấy dữ liệu qua mạng hoặc tính toán một cái gì đó và cung cấp các kết quả cho các hoạt động cần thiết. Mỗi dịch vụ kế thừa từ lớp cơ sở Service.
- Có thể kết nối hay binding đến một dịch vụ đang diễn ra (ongoing) và start một dịch vụ nếu nó chưa được chạy. Trong khi kết nối, bạn có thể giao tiếp với dịch vụ thông qua một giao diện mà dịch vụ expose. Đối với các dịch vụ âm nhạc, giao diện này cho phép người dùng có thể tạm dừng, tua lại, dừng lại, và khởi động lại playback.
- Cũng giống như các Activities và các thành phần khác, các dịch vụ chạy trong các thread chính của tiến trình ứng dụng. Vì vậy, chúng sẽ không ngăn chặn các thành phần khác hoặc giao diện người dùng, chúng thường sản sinh ra một thread khác cho các task tốn thời gian.
3. Broadcast Receivers
- Một Broadcast Receiver là một thành phần không làm gì nhưng nhận và phản ứng với thông báo broadcast. Nhiều broadcast hình thành trong mã nguồn hệ thống - ví dụ, thông báo các múi giờ đã thay đổi, pin yếu, một hình ảnh đã được thực hiện, hoặc để user thay đổi tuỳ chọn ngôn ngữ. Ứng dụng cũng có thể start broadcast - ví dụ, để cho các ứng dụng khác biết rằng một số dữ liệu đã được tải về điện thoại và sẵn có cho chúng để sử dụng.
- Một ứng dụng có thể có nhiều Broadcast Receiver để đáp ứng với bất kỳ thông báo nào mà nó coi là quan trọng. Mọi Receiver đề kế thừa từ lớp cơ sở BroadcastReceiver.
- Broadcast Receivers không hiển thị một giao diện người dùng. Tuy nhiên, chúng có thể bắt đầu một Activity để đáp ứng các thông tin mà chúng nhận được, hoặc có thể sử dụng các NotificationManager để cảnh báo cho người dùng. Notifications có thể nhận được sự chú ý của người dùng trong nhiều cách khác nhau - nhấp nháy đèn, rung thiết bị, chơi một đoạn nhạc. Chúng thường đặt một icon liên tục trong status bar, người dùng có thể mở để nhận được thông báo.
4. Content Providers
- Một Content Provider tạo ra một tập hợp dữ liệu của ứng dụng sẵn có cho các ứng dụng khác. Các dữ liệu có thể được lưu trữ trong hệ thống tập tin, trong một cơ sở dữ liệu SQLite, hoặc bằng bất cứ cách khác có ý nghĩa. Content Provider kế thừa từ lớp cơ sở ContentProvider để thực thi một tập các phương pháp chuẩn cho phép các ứng dụng khác lấy và lưu trữ dữ liệu của các loại mà nó điều khiển. Tuy nhiên, các ứng dụng không gọi những phương thức này một cách trực tiếp. Thay vào đó, chúng sử dụng một đối tượng ContentResolver và gọi các phương thức của lớp này để thay thế. Một ContentResolver có thể trao đổi với bất kỳ content provider nào, nó hợp tác với provider để quản lý bất kỳ giao tiếp InterProcess mà nó tham gia.
- Bất cứ khi nào có một yêu cầu cần được xử lý bởi một thành phần cụ thể, Android đảm bảo rằng tiến trình ứng dụng của thành phần đang chạy, start nó nếu cần thiết, và một thể hiện (instance) thích hợp của thành phần có sẵn, tạo ra instance nếu cần thiết.
5. Activating components: intents
- Content Providers được kích hoạt khi chúng là đích đến(target) bởi một yêu cầu từ ContentResolver; 3 thành phần khác: Activities, Services và Broadcast Receiver được kích hoạt bởi các thông điệp bất đồng bộ gọi là Intents. Một intent là một đối tượng Intent nắm giữ nội dung thông điệp.
- Đối với Activities và Services, nó xác định các hành động được yêu cầu và quy định các URI của dữ liệu để hoạt động. Ví dụ, nó có thể truyền đạt một yêu cầu cho một Acitivity để trình bày một hình ảnh đến user hoặc cho user chỉnh sửa một số văn bản.
- Đối với Broadcast Receivers, đối tượng Intent xác định hành động được công bố. Ví dụ, nó có thể thông báo đến các bên quan tâm rằng các button camera đã được nhấn.
- Một Activity được launch bằng cách gán một đối tượng Intent làm đối số cho phương thức Context.startActivity() hoặc Activity.startActivityForResult(). Acitivity hồi đáp có thể nhìn vào intent tạo ra nó để được launch bằng cách gọi phương thức getIntent(). Android gọi phương thức onNewIntent() của Activity để gán nó vào các intents tiếp theo. Nếu một Activity trả về từ một Activity đang starting, gọi phương thức startActivityForResult() thay vì gọi phương thức startActivity(). Ví dụ, nếu nó bắt đầu một Activity cho phép người dùng chọn một hình ảnh, nó có thể mong muốn để được trả về các bức ảnh được chọn. Kết quả trả về là một đối tượng Intent mà được gán vào phương thức onActivityResult() của Activity.
- Một Service được bắt đầu (hoặc hướng dẫn mới được đưa vào một Service ongoing) bằng cách truyền một đối tượng Intent vào phương thức Context.startService() . Android gọi phương thức onStart() của Service và gán đối tượng Intent này vào. Tương tự như vậy, một intent có thể được gán vào phương thức Context.bindService() để thiết lập một kết nối liên tục giữa các thành phần gọi và một dịch vụ đích. Dịch vụ này nhận được đối tượng Intent trong lời gọi onBind(). (Nếu dịch vụ không phải là đang chạy, bindService() có thể start nó.) Ví dụ, một Activity có thể thiết lập kết nối với Service playback music đã đề cập trước đó để nó có thể cung cấp cho người dùng các phương tiện (một giao diện người dùng) nhằm kiểm soát playback. Activity sẽ gọi phương thức bindService() để thiết lập các kết nối, và sau đó gọi các phương thức được định nghĩa bởi dịch vụ này để tác động đến playback.
- Một ứng dụng có thể khởi tạo một broadcast bằng cách gán một đối tượng Intent vào phương thức Context.sendBroadcast(), Context.sendOrderedBroadcast(), và Context.sendStickyBroadcast() trong bất kỳ trường hợp nào.
6. Shutting down components
- Một Content Provider được kích hoạt chỉ khi nó đáp ứng một yêu cầu từ một đối tượng ContentResolver. Và Broadcast Receiver được kích hoạt chỉ khi nó đáp ứng một thông điệp broadcast. Vì vậy, không cần phải kết thúc các thành phần này.
- Mặc khác, Activities cung cấp giao diện người dùng. Chúng giao tiếp thường xuyên và lâu dài với user và có thể vẫn hoạt động ngay cả khi nhàn rỗi, miễn là sự giao tiếp đó vẫn tiếp tục. Tương tự như vậy, Services cũng có thể tiếp tục chạy trong một thời gian dài. Vì vậy, Android có các phương thức kết thúc Activities và Services một cách có trật tự:
- Một Activity được kết thúc bằng cách gọi phương thức finish(). Một Activity có thể kết thúc một Activity khác bằng cách gọi phương thức finishActivity().
- Một Service được kết thúc bằng cách gọi phương thức stopSelf() hay Context.stopService().
- Các Component cũng có thể được kết thúc bởi hệ thống khi chúng không còn được sử dụng hoặc khi Android phải lấy lại bộ nhớ cho nhiều thành phần khác cần tài nguyên để hoạt động.
7. The manifest file
- Trước khi Android có thể bắt đầu một thành phần ứng dụng, nó phải biết thành phần đó tồn tại. Do đó, các ứng dụng khai báo các thành phần của chúng trong một file manifest được bundled vào trong Android package, file .apk mà cũng có code, các file , và tài nguyên của ứng dụng.
- Manifest là một file XML có cấu trúc và luôn được đặt tên AndroidManifest.xml cho mọi ứng dụng.
- Nhiệm vụ chính của Manifest là để thông báo cho Android về các component của ứng dụng. Ví dụ, một Activity có thể được khai báo như sau:
<?xml version="1.0" encoding="utf-8"?>
<manifest . . . >
<application . . . >
<activity android:name="com.example.project.FreneticActivity"
android:icon="@drawable/small_pic.png"
android:label="@string/freneticLabel"
. . . >
</activity>
. . .
</application>
</manifest>
8. Intent filters
- Một đối tượng Intent có thể khai báo tường minh hay ngầm định. Nếu nó được khai báo tường mình thì Android sẽ dễ dàng tìm ra component đó (dựa vào khai báo trong file manifest), đồng thời kích hoạt nó. Nhưng nếu nó được khai báo ngầm định, Android phải xác định vị trí của component tốt nhất đáp ứng Intent.
- Intent filters sử dụng để thông báo cho Android các loại intent có thể xử lý, và nó cũng được khai báo trong file manifest.
Ví dụ:
<?xml version="1.0" encoding="utf-8"?> <manifest . . . > <application . . . > <activity android:name="com.example.project.FreneticActivity" android:icon="@drawable/small_pic.png" android:label="@string/freneticLabel" . . . > <intent-filter . . . > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter . . . > <action android:name="com.example.project.BOUNCE" /> <data android:mimeType="image/jpeg" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> . . . </application> </manifest> |