Erstellen und Freigeben einer Datei aus internem Speicher

Mein Ziel ist es, eine XML-Datei im internen Speicher zu erstellen und sie dann über die Freigabe zu senden.

Ich bin in der Lage, eine XML-Datei mit diesem Code zu erstellen

  • So erhalten Sie den Dateinamen, wenn Sie auf URL in Webview klicken
  • Wie kann ich Dalvik kompilieren, um es lokal auf Linux zu führen?
  • Android ArrayList von benutzerdefinierten Objekten - In SharedPreferences speichern - Serializable?
  • Gespannte Spalten kollabieren auf Android-Web-Browser (bei der Verwendung von Auto-Fit-Seiten)
  • C / C ++ printfs - Wo wird es in einem Android nativen Code angezeigt?
  • Android Plattenspielplatz Video
  • FileOutputStream outputStream = context.openFileOutput(fileName, Context.MODE_WORLD_READABLE); PrintStream printStream = new PrintStream(outputStream); String xml = this.writeXml(); // get XML here printStream.println(xml); printStream.close(); 

    Ich stecke fest, um ein Uri zur Ausgabedatei abzurufen, um es zu teilen. Ich habe zuerst versucht, die Datei zugreifen, indem ich die Datei in eine Uri umwandle

     File outFile = context.getFileStreamPath(fileName); return Uri.fromFile(outFile); 

    Dies gibt die Datei zurück: ///data/data/com.my.package/files/myfile.xml aber ich kann es nicht scheinen, diese an eine E-Mail zu senden , hochzuladen usw.

    Wenn ich die Dateilänge manuell überprüfe, ist es richtig und zeigt, dass es eine angemessene Dateigröße gibt.

    Als nächstes habe ich einen Content-Provider erstellt und versucht, die Datei zu verweisen und es ist kein gültiger Handle für die Datei. Der ContentProvider scheint niemals irgendeinen Punkt zu nennen.

     Uri uri = Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/" + fileName); return uri; 

    Das gibt den Inhalt: //com.my.package.provider/myfile.xml aber ich überprüfe die Datei und es ist null Länge.

    Wie kann ich auf Dateien richtig zugreifen? Muss ich die Datei mit dem Content Provider erstellen? Wenn das so ist, wie?

    Aktualisieren

    Hier ist der Code, den ich benutze, um zu teilen. Wenn ich Gmail auswähle, zeigt es als Anhang an, aber wenn ich es sende, gibt es einen Fehler Kann nicht Anhang anzeigen und die E-Mail, die ankommt, hat keine Anlage.

     public void onClick(View view) { Log.d(TAG, "onClick " + view.getId()); switch (view.getId()) { case R.id.share_cancel: setResult(RESULT_CANCELED, getIntent()); finish(); break; case R.id.share_share: MyXml xml = new MyXml(); Uri uri; try { uri = xml.writeXmlToFile(getApplicationContext(), "myfile.xml"); //uri is "file:///data/data/com.my.package/files/myfile.xml" Log.d(TAG, "Share URI: " + uri.toString() + " path: " + uri.getPath()); File f = new File(uri.getPath()); Log.d(TAG, "File length: " + f.length()); // shows a valid file size Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, uri); shareIntent.setType("text/plain"); startActivity(Intent.createChooser(shareIntent, "Share")); } catch (FileNotFoundException e) { e.printStackTrace(); } break; } } 

    Ich habe bemerkt, dass es hier eine Exception , die hier von innen erstellt wird. Schöpfer (…) , aber ich kann nicht herausfinden, warum es geworfen wird.

    E / ActivityThread (572): Aktivität com.android.internal.app.ChooserActivity hat IntentReceiver com.android.internal.app.ResolverActivity$1@4148d658 ausgelaufen, das ursprünglich hier registriert wurde. Fehlt Ihnen ein Aufruf von unregisterReceiver ()?

    Ich habe diesen Fehler recherchiert und kann nichts offensichtliches finden. Beide Links deuten darauf hin, dass ich einen Empfänger aufheben muss.

    • ChooserActivity hat IntentReceiver durchgesickert
    • Warum braucht Intent.createChooser () einen BroadcastReceiver und wie man implementiert?

    Ich habe einen Receiver Setup, aber es ist für einen AlarmManager , der anderswo eingestellt ist und nicht die App benötigt, um sich zu registrieren / unregistrieren.

    Code für openFile (…)

    Falls es nötig ist, hier ist der Content Provider, den ich erstellt habe.

     public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { String fileLocation = getContext().getCacheDir() + "/" + uri.getLastPathSegment(); ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY); return pfd; } 

  • Wenden Sie ein Thema auf eine Aktivität in Android?
  • Bessere Möglichkeit, einen Android x86 HAXM beschleunigten Emulator auf Windows 8 mit Hyperv zu verwenden
  • PreferenceActivity Update Zusammenfassung
  • Building Android Studio Projekt auf Jenkins? android.compileSdkVersion fehlt
  • Android Holo Ausgewählte Liste Artikel Farbe
  • Wie kann ich Titeln in ViewPager mit Fragmenten setzen?
  • 3 Solutions collect form web for “Erstellen und Freigeben einer Datei aus internem Speicher”

    Es ist möglich, eine Datei, die in einem privaten Verzeichnis der Apps gespeichert ist, über einen ContentProvider aufzudecken. Hier ist ein Beispielcode, den ich gemacht habe, wie man einen Content Provider erstellt, der dies tun kann.

    Manifest

     <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.providertest" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="15" /> <application android:label="@string/app_name" android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="MyProvider" android:authorities="com.example.prov" android:exported="true" /> </application> </manifest> 

    In Ihrem ContentProvider überschreiben Sie openFile, um den ParcelFileDescriptor zurückzusenden

     @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { File cacheDir = getContext().getCacheDir(); File privateFile = new File(cacheDir, "file.xml"); return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY); } 

    Stellen Sie sicher, dass Sie Ihre XML-Datei in das Cache-Verzeichnis kopiert haben

      private void copyFileToInternal() { try { InputStream is = getAssets().open("file.xml"); File cacheDir = getCacheDir(); File outFile = new File(cacheDir, "file.xml"); OutputStream os = new FileOutputStream(outFile.getAbsolutePath()); byte[] buff = new byte[1024]; int len; while ((len = is.read(buff)) > 0) { os.write(buff, 0, len); } os.flush(); os.close(); is.close(); } catch (IOException e) { e.printStackTrace(); // TODO: should close streams properly here } } 

    Jetzt sollten alle anderen Apps in der Lage sein, ein InputStream für Ihre private Datei zu erhalten, indem Sie den Inhalt uri (content: //com.example.prov/myfile.xml)

    Für einen einfachen Test rufen Sie den Content Provider aus einer separaten App wie folgt auf

      private class MyTask extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... params) { Uri uri = Uri.parse("content://com.example.prov/myfile.xml"); InputStream is = null; StringBuilder result = new StringBuilder(); try { is = getApplicationContext().getContentResolver().openInputStream(uri); BufferedReader r = new BufferedReader(new InputStreamReader(is)); String line; while ((line = r.readLine()) != null) { result.append(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) is.close(); } catch (IOException e) { } } return result.toString(); } @Override protected void onPostExecute(String result) { Toast.makeText(CallerActivity.this, result, Toast.LENGTH_LONG).show(); super.onPostExecute(result); } } 

    Also Rob's Antwort ist richtig, ich nehme an, aber ich habe es ein bisschen anders gemacht. Soweit ich verstehe, mit der Einstellung im Anbieter:

     android:exported="true" 

    Sie geben öffentlichen Zugriff auf alle Ihre Dateien ?! Wie auch immer, eine Möglichkeit, nur Zugriff auf einige Dateien zu geben, besteht darin, Dateipfadberechtigungen auf folgende Weise zu definieren:

     <provider android:authorities="com.your.app.package" android:name="android.support.v4.content.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> 

    Und dann in Ihrem XML-Verzeichnis definieren Sie file_paths.xml Datei wie folgt:

     <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path path="/" name="allfiles" /> <files-path path="tmp/" name="tmp" /> </paths> 

    Jetzt, die "allfiles" gibt die gleiche Art von öffentlichen Erlaubnis Ich denke, wie die Option android: exportiert = "true" aber du willst nicht wirklich, dass ich denke, so dass ein Unterverzeichnis definieren ist die nächste Zeile. Dann alles, was Sie tun müssen, ist die Dateien zu speichern, die Sie teilen möchten, dort in diesem Verzeichnis.

    Weiter, was du tun musst, ist, wie auch Rob sagt, einen URI für diese Datei erhalten. So habe ich es gemacht:

     Uri contentUri = FileProvider.getUriForFile(context, "com.your.app.package", sharedFile); 

    Dann, wenn ich diesen URI habe, musste ich an ihm die Berechtigungen für andere App anbringen, um es zu benutzen. Ich benutzte oder schickte diese Datei URI zur Kamera-App. Auf jeden Fall ist dies die Art und Weise, wie ich die anderen App-Paket-Info und gewährte Berechtigungen für die URI:

     PackageManager packageManager = getPackageManager(); List<ResolveInfo> list = packageManager.queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY); if (list.size() < 1) { return; } String packageName = list.get(0).activityInfo.packageName; grantUriPermission(packageName, sharedFileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); ClipData clipData = ClipData.newRawUri("CAMFILE", sharedFileUri); cameraIntent.setClipData(clipData); cameraIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); cameraIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivityForResult(cameraIntent, GET_FROM_CAMERA); 

    Ich habe den Code für Kamera verlassen, da ich kein anderes Beispiel machen wollte, an dem ich nicht gearbeitet habe. Aber auf diese Weise sehen Sie, dass Sie Berechtigungen an URI selbst anhängen können.

    Die Kamera ist, dass ich es über ClipData einstellen und dann zusätzlich Berechtigungen setzen kann. Ich denke, in Ihrem Fall benötigen Sie nur FLAG_GRANT_READ_URI_PERMISSION, da Sie eine Datei an eine E-Mail anhängen.

    Hier ist der Link zu FileProvider zu helfen, da ich alle meine Post auf die Info, die ich dort gefunden habe. Hatte einige Schwierigkeiten, ein Paket Info für Kamera App zu finden.

    Ich hoffe es hilft.

    Wenn Sie andere Apps benötigen, um die privaten Dateien Ihrer App zu sehen (für Freigeben oder anderweitig), können Sie einige Zeit sparen und nur den FileProvider der v4 compat-Bibliothek verwenden

    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.