2010-01-02 24 views
57

Bir uygulama yapmak için öncelikle Android NDK kullanıyorum performans nedenleriyle, ancak fopen gibi dosya işlemleri Android'de düzgün çalışmıyor. Bu işlevleri kullanmaya çalıştığımda, uygulama çöküyor.Android'de Dosya İşlemleri NDK

Android NDK ile bir dosyaya nasıl yazabilirim/yazarım?

+1

Bunu güncellemeyi unuttunuz. Sorunun kökü okuma/yazma izinleri almıyordu. Benzer bir sorun, sdcard'ın takılı olması ve daha sonra bir dosyayı açmaya çalışmaktan da kaynaklanabilir. – RyanCheu

+0

U ile aynı sorunu yaşıyorum, bunu çözdünüz mü? –

cevap

51

Yukarıdakilerin tümü doğrudur. Dosyayı NDF aracılığıyla FILE ve fopen kullanarak açabilirsiniz. AMA ... Bunun için izin vermeyi unutmayın. yeni cihazlar sadece "/ sdcard" eşlemek olmadığı için Android'de bir

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
+0

Bu satırı bildirim dosyasında nereye koyacağız? – Dhasneem

+0

Bildiride http://developer.android.com/guide/topics/manifest/uses-permission-element.html –

+0

Teşekkürler, işe yarıyor! Ayrıca, manifest dosyasındaki güncellemelerin yalnızca uygulamayı yeniden yükledikten sonra yürürlüğe gireceğini öğrendim. Bazen tutulma sizin için uygulamayı yeniden yüklemez. Uygulamayı telefonumdan sildim ve eclipse kullanarak tekrar yükledim. –

57

Dosya IO, JNI kullanarak Android'de iyi çalışıyor. Belki de bir dosyayı kötü bir yolla açmaya çalışıyorsunuz ve dönüş kodunu kontrol etmiyorsunuz? Merhaba-jni örneğini, dosyayı açıp ona yazmanın gerçekten mümkün olduğunu göstermek için değiştirdim. Umarım bu yardımcı olur. İşte

/* 
* Copyright (C) 2009 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
* 
*/ 
#include <string.h> 
#include <jni.h> 
#include <stdio.h> 

/* This is a trivial JNI example where we use a native method 
* to return a new VM String. See the corresponding Java source 
* file located at: 
* 
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java 
*/ 
jstring 
Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env, 
               jobject thiz) 
{ 
    FILE* file = fopen("/sdcard/hello.txt","w+"); 

    if (file != NULL) 
    { 
     fputs("HELLO WORLD!\n", file); 
     fflush(file); 
     fclose(file); 
    } 

    return (*env)->NewStringUTF(env, "Hello from JNI (with file io)!"); 
} 

(SD kart ile) telefonumda bunu çalıştırdıktan sonra sonuç geçerli:

$ adb -d shell cat /sdcard/hello.txt 
HELLO WORLD! 
+0

Teşekkürler, bu işe yarıyor! Benim sorunum, fopen komutum için tam bir yol kullanmadığımdı. – RyanCheu

+2

Öğelerdeki salt okunur modda bulunan bir dosyayı açmak mümkün mü? – dzhelil

+1

NDK kullanarak varlıkların açılması daha karmaşıktır ancak gerekli adımları burada açıklarım. [Http://stackoverflow.com/questions/2651816/reading-resource-files-from-my-own-apk-in-android-native/2663962 # 2663962) -Çevre. –

18

Ben de düzgün çalışır) (yani fopen doğrulayabilir, ancak değil sen eğer uygulamanın kaynak veya varlıkları klasöründeki bir dosyaya erişmeye çalışmak. Tekerleği yeniden icat etmekten kaçınmak için, uygulamanızla birlikte göndermek istediğiniz varlıkları, dağıtım için paketlenecekleri varlıklar klasörüne yapıştırmanızı tavsiye ederim.

Öğeler klasöründe, dosyanın paketleyici tarafından sıkıştırılıp sıkıştırılmadığına bağlı olarak iki şeyden birini yapmanız gerekir. Her ikisi de AssetManager yöntemlerini kullanır ve AssetManager'ı içerik/uygulamadan alabilirsiniz. Dosya adları her zaman varlıklar klasörüne göredir, btw: Varlıkları klasöründe doğrudan "foo.png" dosyanız varsa "foo.png", "" "assets/foo.png" gibi bir şey açmazsınız .

  1. dosya sıkıştırılmış değildi (yani, bu .png gibi sıkıştırılmış almaz uzantıları biri) size AssetManager.openFd (bir dosya tanıtıcı almak) ve onu geçebilir, C++. Sonra fdopen kullanabilirsiniz (dup (fd), "r"); dosyayı bir dosya olarak açmak için *. Not , ofseti fseek() ile işaretleyin ve dosyanın uzunluğunu kendiniz izleyin. Gerçekten tüm varlık paketine bir dosya tanıtıcısı alıyorsunuz ve ilgilendiğiniz dosya sadece küçük bir bölüm.

  2. Dosyanız sıkıştırılmışsa, Java akış okuyucusunu kullanmanız gerekir: AssetManager.open() size dosyayı okuyabileceğiniz bir InputStream verir. Bu bir PITAdır çünkü sorgulayamazsınız (AFAIK) dosya boyutu; Tüm dosyaların boyutlarını içeren bir klasör oluşturan öğeler klasörümde bir önişleme adımı çalıştırıyorum, böylece bir arabelleğin ne kadar büyük bir alana yayılacağını biliyorum. Dosyanız bir kaynaktır Eğer kaynaklar aynı varlıklar paketin içine paketlenmiş görünür olsa

, sen erişmek için Kaynak sınıfına geçmesi gerekebilir. Kaynak, yukarıda açıklandığı gibi dosya tanımlayıcısını almak için InputStream ve openRawResourceFd() çağrısını almak için openRawResource() çağrısı vardır.

İyi şanslar.

+0

Takip notu: "AssetManager.openFd() 'dan bir dosya tanıtıcısı almak" kötü biçimden çıkıyor - mübarek SDK'nın bir parçası değil. Mevcut tüm telefonlarda çalışır, ancak çalışmaya devam etmesi garanti edilmez. .APK dosyasının yolunu bulmak zor olmayacak ve okuyucunun NDK kodunun tamamen kaybolmasını sağlayan bir alıştırma olarak bırakıldı. – SomeCallMeTim

18

sdcard gerçek yolunu almak için Java getExternalStorageDirectory() çağrıyı kullandığınızdan emin olun yerleştirmek manifestosunda.Bu durumda, sabit kodlanmış bir "/ sdcard" konumu denemesi başarısız olur.

+3

Bu gerçekten çok önemli – KaiserJohaan