學習安卓開發[4] - 使用隱式Intent啟動簡訊、聯繫人、相機應用

来源:https://www.cnblogs.com/zhixin9001/archive/2019/01/03/10212214.html
-Advertisement-
Play Games

在上一篇 學習安卓開發[3] 使用RecyclerView顯示列表 中瞭解了在進行列表展示時RecyclerView的使用,本次記錄的是在應用中如何通過隱式Intent調用其它應用的功能,比如發簡訊、打電話、拍照等 隱式Intent 簡訊 判斷是否存在相關APP 相機 FileProvider Bi ...


在上一篇學習安卓開發[3] - 使用RecyclerView顯示列表中瞭解了在進行列表展示時RecyclerView的使用,本次記錄的是在應用中如何通過隱式Intent調用其它應用的功能,比如發簡訊、打電話、拍照等

  • 隱式Intent
  • 簡訊
    • 判斷是否存在相關APP
  • 相機
    • FileProvider
    • Bitmap
    • 功能聲明

隱式Intent

Intent對象用來向操作系統說明需要處理的任務。使用顯式Intent時,要指定操作系統需要啟動的activity,但使用隱式intent,只需告知操作系統想要進行的操作,系統就會啟動能完成該操作的activity,如果有多個符合條件的activity,會提供用戶一個應用列表供選擇
Android是如何通過隱式intent找到並啟動合適應用的呢?原因在於配置文件中的itent過濾器設置,比如我們也想開發一款簡訊應用,那麼可以在AndroidMainfest的activity聲明中這樣設置:

<activity android:name=".CrimeListActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

隱式Intent的組成部分有
1)要執行的操作,通常以Intent類中的常量來表示,比如訪問URL可以使用Intent.ACTION_VIEW,發送郵件使用Intent.ACTION_SEND
2)待訪問數據的位置,這可能是設備以外的資源,如某個網頁的URL,某個文件的URI
3)操作涉及的數據類型,如text/html, audio/mpeg3等
4)可選類別,用來描述對activity的使用方式

簡訊

那麼要啟動簡訊的隱式intent的方法為:

mReportButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("text/plain");
        i.putExtra(Intent.EXTRA_TEXT, getCrimeReport());
        i.putExtra(Intent.EXTRA_SUBJECT,
                getString(R.string.crime_report_suspect));
        i = Intent.createChooser(i, getString(R.string.send_report));
        startActivity(i);
    }
});

首先指定發送消息的操作名為ACTION_SEND,然後消息內容為文本,所以設置數據類型為text/plain,要發送的文本通過Extra的形式提供

判斷是否存在相關APP

使用隱式intent時,如果系統沒有安裝對應的軟體,應用就會奔潰,所以有必要在使用隱式intent時,檢查一下能夠找到對應的軟體,如果沒找到,就避免再去發生相關的隱式intent

final Intent pickContact = new Intent(Intent.ACTION_SEND);
PackageManager packageManager = getActivity().getPackageManager();
    if (packageManager.resolveActivity(pickContact, PackageManager.MATCH_DEFAULT_ONLY) == null) {
        mReportButton.setEnabled(false);
}

通過PackageManager可以搜索需要的activity的信息,flag標誌MATCH_DEFAULT_ONLY限定只搜索帶CATEGORY_DEFAULT的activity,如果沒有找到,就禁用發簡訊按鈕。

相機

如果所開發的APP有拍照功能,就可以使用系統相機了。拍攝的照片要保存在設備文件系統,但這就涉及到私有存儲空間的問題。出於安全考慮,無法使用公共外部存儲轉存,那麼如果想共用文件給其他應用,或者接收其他應用的文件(如相機拍攝的照片),可以使用ContentProvider把要共用的文件臨時暴露出來。對於接受相機拍攝的照片這樣的場景,系統提供的現成的FileProvider類。

FileProvider

要使用FileProvider類,需要在AndroidMainfest中添加聲明。
首先添加files.xml文件

<paths>
    <files-path
        name="crime_photos"
        path="."/>
</paths>

這個描述性文件把私有存儲空間的根路徑映射為crime_photos,這個名字僅供FileProvider自己使用。
然後添加FileProvider聲明:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.zhixin.crimeintent.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/files" />
</provider>

通過這段聲明,提供了一個文件保存地,相機拍攝的照片就可以放在這裡了。exported="false"表示除了應用自己和給予授權的應用,其它的不允許使用這個FileProvider,grantUriPermissions="true"表示允許其他應用向指定文職的URI寫入文件。

接下來就可以實現拍照功能了

mPhotoButton = (ImageButton) v.findViewById(R.id.crime_camera);
final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
boolean canTakePhoto = mPhotoFile != null &&
        captureImage.resolveActivity(packageManager) != null;
mPhotoButton.setEnabled(canTakePhoto);

mPhotoButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Uri uri = FileProvider.getUriForFile(getActivity(),
                "com.example.zhixin.crimeintent.fileprovider", mPhotoFile);
        captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri);

        List<ResolveInfo> cameraActivities = getActivity().getPackageManager().queryIntentActivities(captureImage,
                PackageManager.MATCH_DEFAULT_ONLY);

        for (ResolveInfo activity : cameraActivities) {
            getActivity().grantUriPermission(activity.activityInfo.packageName,
                    uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }

        startActivityForResult(captureImage,REQUEST_PHOTO);
    }
});

mPhotoView = (ImageView) v.findViewById(R.id.crime_photo);

通過給所有目標activity授予Intent.FLAG_GRANT_WRITE_URI_PERMISSION許可權,允許它們在URI指定的位置寫入文件。mPhotoFile表示拍攝生成照片的名稱。

在相機拍攝完成後的回調方法中,取消之前的Intent.FLAG_GRANT_WRITE_URI_PERMISSION授權,並載入顯示照片。

Uri uri=FileProvider.getUriForFile(getActivity(),
        "com.example.zhixin.crimeintent.fileprovider",
        mPhotoFile);
getActivity().revokeUriPermission(uri,Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
updatePhotoView();
Bitmap

在顯示照片時還有一些工作要做。顯示照片要用到Bitmap,而Bitmap只存儲實際像素數據,即使是已經壓縮過的照片,存入Bitmap後,文件並不會同樣壓縮,比如一張1600萬像素24位的相機照片存為JPG格式約為5MB,但載入Bitmap後就會達到48MB左右。
要解決這個問題,需要手動縮放點陣圖照片。首先確認文件大小,然後根據要顯示照片的區域大小合理縮放文件,最後重新讀取縮放後的文件,再創建Bitmap對象。

public class PictureUtils {
    public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
        // Read in the dimensions of the image on disk
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        float srcWidth = options.outWidth;
        float srcHeight = options.outHeight;

        // Figure out how much to scale down by
        int inSampleSize = 1;
        if (srcHeight > destHeight || srcWidth > destWidth) {
            float heightScale = srcHeight / destHeight;
            float widthScale = srcWidth / destWidth;

            inSampleSize = Math.round(heightScale > widthScale ? heightScale :
                    widthScale);
        }

        options = new BitmapFactory.Options();
        options.inSampleSize = inSampleSize;

        // Read in and create final bitmap
        return BitmapFactory.decodeFile(path, options);
    }
}

還有一個問題是在Fragment.OnCreateView裡面載入照片的時候,無法知道要顯示照片的尺寸,只有onCreate, onStart, onResume方法執行過後,才會有首個實例化佈局出現。對於這種情況,可以根據Fragment所在的Activity尺寸確定屏幕的尺寸,按照屏幕尺寸縮放圖像。所以再添加一個getScaledBitmap的重載:

public static Bitmap getScaledBitmap(String path, Activity activity) {
    Point size = new Point();
    activity.getWindowManager().getDefaultDisplay()
            .getSize(size);
    return getScaledBitmap(path, size.x, size.y);
}

最後在OnCreateView和相機的回調方法更新照片。

功能聲明

既然APP需要用到拍照功能,但像拍照、NFC、紅外等並不是每個設備都有,所以進行功能聲明,從而可以在應用前讓用戶知道,如果設備缺少某項必須功能,應用商店會拒絕安裝應用。
在AndroidMainfest中添加:

<uses-feature
    android:name="android.hardware.camera"
    android:required="false">
</uses-feature>

android:required="false"表示不強制拍照功能,因為如果設備沒有相機,會禁掉拍照按鈕。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡單的SQL語句增刪改查操作 說明: 在mysql裡面親測結果正確 用到的表(學生表:studnets) 1.創建一個學生表,(學號,姓名,性別,家庭住址) mysql> create table students -> ( -> studentId int(11) not null primary ...
  • 刪除登陸賬戶註意事項 不能刪除正在登錄的登錄名。 也不能刪除擁有任何安全對象、伺服器級對象或 SQL Server 代理作業的登錄名。 可以刪除資料庫用戶映射到的登錄名,但是這會創建孤立用戶。 有關詳細信息,請參閱 孤立用戶故障排除 (SQL Server)。 在 SQL Database中,對連接 ...
  • 本文由雲+社區發表 文章《MySQL查詢分析》講述了使用MySQL慢查詢和explain命令來定位mysql性能瓶頸的方法,定位出性能瓶頸的sql語句後,則需要對低效的sql語句進行優化。本文主要討論MySQL索引原理及常用的sql查詢優化。 一個簡單的對比測試 前面的案例中,c2c_zwdb.t_ ...
  • 場景: Aix 7.2 上安裝Oracle 18.4 RAC 執行root.sh腳本,ASM failed to start !查看日誌文件:ORA-40238: invalid linear algebra shared library /u01/app/oracle/product/18.0.0 ...
  • MySQL資料庫設計規範 目錄 1. 規範背景與目的 MySQL資料庫與 Oracle、 SQL Server 等資料庫相比,有其內核上的優勢與劣勢。我們在使用MySQL資料庫的時候需要遵循一定規範,揚長避短。本規範旨在幫助或指導RD、QA、OP等技術人員做出適合線上業務的資料庫設計。在資料庫變更和 ...
  • 【作者】 劉博:攜程技術保障中心資料庫高級經理,主要關註Sql server和Mysql的運維和故障處理。 【環境】 版本號:5.6.21 隔離級別:REPEATABLE READ 【問題描述】 接到監控報警,有一個線上的應用DeadLock報錯,每15分鐘會準時出現,報錯統計如下圖: 登錄Mysq ...
  • 什麼是Redis的併發競爭問題 Redis的併發競爭問題,主要是發生在併發寫競爭。考慮到redis沒有像db中的sql語句,update val = val + 10 where ...,無法使用這種方式進行對數據的更新。 假如有某個key(mileage), value(10),現在想把value ...
  • 自從成為架構師()之後,李大胖的學習動力似乎少了一些,尤其是今年(當然也有一些客觀因素)。 臨近歲末,內心著實有些慚愧,決定學習一把大數據。跟隨一下業界前沿(其實已經不是前沿了),夢想著有一天能夠擁有擁有夢想的權力。 操練起來 啟動裝有CentOS的虛擬機(IP是172.18.232.181),按照 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...