當應用程式想要存取其他應用程式共用的檔案時,提出要求的應用程式 (用戶端)
通常會傳送要求至共用檔案的應用程式 (伺服器)。在大多數情況下
在伺服器應用程式中啟動 Activity
,顯示可共用的檔案。
使用者選取檔案,然後伺服器應用程式就會將檔案的內容 URI 傳回給
用戶端應用程式。
本課程會說明用戶端應用程式如何從伺服器應用程式要求檔案、接收檔案的 內容 URI,並使用內容 URI 開啟檔案。
傳送檔案要求
如要從伺服器應用程式要求檔案,用戶端應用程式會呼叫
startActivityForResult
,其中包含
Intent
,包含動作,例如
ACTION_PICK
和用戶端應用程式的 MIME 類型
可以處理
舉例來說,下列程式碼片段示範如何將
Intent
傳送至伺服器應用程式,才能啟動
Activity
共用檔案一文中所述:
Kotlin
class MainActivity : Activity() { private lateinit var requestFileIntent: Intent private lateinit var inputPFD: ParcelFileDescriptor ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) requestFileIntent = Intent(Intent.ACTION_PICK).apply { type = "image/jpg" } ... } ... private fun requestFile() { /** * When the user requests a file, send an Intent to the * server app. * files. */ startActivityForResult(requestFileIntent, 0) ... } ... }
Java
public class MainActivity extends Activity { private Intent requestFileIntent; private ParcelFileDescriptor inputPFD; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestFileIntent = new Intent(Intent.ACTION_PICK); requestFileIntent.setType("image/jpg"); ... } ... protected void requestFile() { /** * When the user requests a file, send an Intent to the * server app. * files. */ startActivityForResult(requestFileIntent, 0); ... } ... }
存取要求的檔案
伺服器應用程式會將檔案的內容 URI 傳回用戶端應用程式,
Intent
。這個 Intent
會傳遞到用戶端
應用程式在 onActivityResult()
的覆寫值中。一次
用戶端應用程式具有檔案的內容 URI,只要取得該檔案
FileDescriptor
。
只要您正確剖析內容 URI,這個程序才會保留檔案安全性。 用戶端應用程式收到的回應要求剖析內容時,您必須確定這個 URI 不會指向 加入目標目錄以外的任何內容,確保沒有 路徑週遊。 只有用戶端應用程式才能取得檔案存取權,且只有用戶端應用程式授予的權限 伺服器應用程式。權限是暫時性的,因此用戶端應用程式的工作堆疊完成後, 無法再透過伺服器應用程式存取這個檔案。
下一段程式碼片段示範用戶端應用程式如何處理
Intent
伺服器應用程式傳送的資料,以及用戶端應用程式如何取得
FileDescriptor
使用內容 URI:
Kotlin
/* * When the Activity of the app that hosts files sets a result and calls * finish(), this method is invoked. The returned Intent contains the * content URI of a selected file. The result code indicates if the * selection worked or not. */ public override fun onActivityResult(requestCode: Int, resultCode: Int, returnIntent: Intent) { // If the selection didn't work if (resultCode != Activity.RESULT_OK) { // Exit without doing anything else return } // Get the file's content URI from the incoming Intent returnIntent.data?.also { returnUri -> /* * Try to open the file for "read" access using the * returned URI. If the file isn't found, write to the * error log and return. */ inputPFD = try { /* * Get the content resolver instance for this context, and use it * to get a ParcelFileDescriptor for the file. */ contentResolver.openFileDescriptor(returnUri, "r") } catch (e: FileNotFoundException) { e.printStackTrace() Log.e("MainActivity", "File not found.") return } // Get a regular file descriptor for the file val fd = inputPFD.fileDescriptor ... } }
Java
/* * When the Activity of the app that hosts files sets a result and calls * finish(), this method is invoked. The returned Intent contains the * content URI of a selected file. The result code indicates if the * selection worked or not. */ @Override public void onActivityResult(int requestCode, int resultCode, Intent returnIntent) { // If the selection didn't work if (resultCode != RESULT_OK) { // Exit without doing anything else return; } else { // Get the file's content URI from the incoming Intent Uri returnUri = returnIntent.getData(); /* * Try to open the file for "read" access using the * returned URI. If the file isn't found, write to the * error log and return. */ try { /* * Get the content resolver instance for this context, and use it * to get a ParcelFileDescriptor for the file. */ inputPFD = getContentResolver().openFileDescriptor(returnUri, "r"); } catch (FileNotFoundException e) { e.printStackTrace(); Log.e("MainActivity", "File not found."); return; } // Get a regular file descriptor for the file FileDescriptor fd = inputPFD.getFileDescriptor(); ... } }
openFileDescriptor()
方法
會傳回檔案的 ParcelFileDescriptor
。在這個物件中
應用程式可取得 FileDescriptor
物件,以便用於讀取檔案。
如需其他相關資訊,請參閱: