jest to dobrze udokumentowany błąd w niektórych wersjach Androida. oznacza to, że w wersjach Androida z doświadczeniem Google przechwytywanie obrazu nie działa zgodnie z dokumentacją. to, czego zwykle używałem, to coś takiego w klasie narzędzi.
public boolean hasImageCaptureBug() {
// list of known devices that have the bug
ArrayList<String> devices = new ArrayList<String>();
devices.add("android-devphone1/dream_devphone/dream");
devices.add("generic/sdk/generic");
devices.add("vodafone/vfpioneer/sapphire");
devices.add("tmobile/kila/dream");
devices.add("verizon/voles/sholes");
devices.add("google_ion/google_ion/sapphire");
return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/"
+ android.os.Build.DEVICE);
}
następnie, kiedy uruchamiam przechwytywanie obrazu, tworzę intencję, która sprawdza, czy nie ma błędu.
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);
następnie w ramach czynności, do której wracam, robię różne rzeczy w zależności od urządzenia.
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case GlobalConstants.IMAGE_CAPTURE:
Uri u;
if (hasImageCaptureBug()) {
File fi = new File("/sdcard/tmp");
try {
u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
if (!fi.delete()) {
Log.i("logMarker", "Failed to delete " + fi);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
u = intent.getData();
}
}
Dzięki temu nie musisz pisać nowej aplikacji aparatu, ale ten kod też nie jest świetny. są duże problemy
nigdy nie otrzymujesz pełnowymiarowych obrazów z urządzeń z błędem. otrzymujesz obrazy o szerokości 512 pikseli, które są wstawiane do dostawcy zawartości obrazu. na urządzeniach bez błędu wszystko działa jak dokument, masz duży normalny obraz.
musisz zachować tę listę. jak napisano, możliwe jest flashowanie urządzeń z wersją Androida (powiedzmy kompilacją CyanogenMod ), która ma naprawiony błąd. jeśli tak się stanie, twój kod ulegnie awarii. rozwiązaniem jest użycie całego odcisku palca urządzenia.
Wiem, że odpowiedź na to pytanie była już wcześniejsza, ale wiem, że wiele osób o to wpadło, więc dodam komentarz.
Dokładnie ten sam problem wystąpił na moim Nexusie One. Pochodziło to z pliku, który nie istniał na dysku przed uruchomieniem aplikacji aparatu. Dlatego upewniłem się, że plik istniejący przed uruchomieniem aplikacji aparatu. Oto przykładowy kod, którego użyłem:
Najpierw tworzę unikalną (nieco) nazwę pliku za pomocą skrótu MD5 i umieszczam ją w odpowiednim folderze. Następnie sprawdzam, czy istnieje (nie powinien, ale dobrą praktyką jest sprawdzenie i tak). Jeśli nie istnieje, otrzymuję katalog nadrzędny (folder) i tworzę do niego hierarchię folderów (dlatego jeśli foldery prowadzące do lokalizacji pliku nie istnieją, będą znajdować się po tym wierszu). Tworzę plik.Po utworzeniu pliku otrzymuję Uri i przekazuję go do celu, a następnie przycisk OK działa zgodnie z oczekiwaniami i wszystko jest złote.
Teraz po naciśnięciu przycisku OK w aplikacji aparatu plik będzie obecny w podanej lokalizacji. W tym przykładzie będzie to /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg
Nie ma potrzeby kopiowania pliku w „onActivityResult”, jak napisano powyżej.
źródło
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
w swoim manifeście, jeśli używasz nowszego niż Android 1.5 - spędziłeś kilka godzin na debugowaniu elementów aparatu, ale nie było to uwzględnione, więc moje zapisy zawsze kończyły się niepowodzeniem.Przeszedłem przez wiele strategii robienia zdjęć i zawsze wydaje się, że istnieje przypadek, platforma lub określone urządzenia, w których niektóre lub wszystkie powyższe strategie zawiodą w nieoczekiwany sposób. Udało mi się znaleźć strategię, która wykorzystuje poniższy kod generowania URI, który wydaje się działać w większości, jeśli nie we wszystkich przypadkach.
Aby przyczynić się do dalszej dyskusji i pomóc nowicjuszom, stworzyłem przykładową / testową aplikację, która pokazuje kilka różnych strategii implementacji robienia zdjęć. Zdecydowanie zachęca się do dodania do dyskusji wkładów z innych implementacji.
https://github.com/deepwinter/AndroidCameraTester
źródło
onActivityResult
czy naprawdę muszę sam go zapamiętać? Musiałbym wytrwale go zapisywać, aby moja aplikacja go zapamiętała, gdyby została zniszczona podczasMiałem ten sam problem, w którym przycisk OK w aplikacji aparatu nic nie robił, zarówno na emulatorze, jak i na Nexusie 1.
Problem zniknął po określeniu bezpiecznej nazwy pliku bez spacji i znaków specjalnych.
MediaStore.EXTRA_OUTPUT
Ponadto, jeśli określasz plik znajdujący się w katalogu, który nie został jeszcze utworzony, musisz go najpierw utworzyć. Aplikacja aparatu nie wykonuje za Ciebie mkdir.źródło
mkdirs()
zamiast tego używasz,mkdir()
jeśli twoja ścieżka ma więcej niż jeden poziom katalogu i chcesz, aby wszystkie zostały utworzone (mkdir
tworzy tylko ostatni, katalog „liść”). Miałem z tym pewne problemy i ta odpowiedź mi pomogła.Opisywany przepływ pracy powinien działać tak, jak go opisałeś. Może pomóc, jeśli pokażesz nam kod wokół tworzenia intencji. Ogólnie rzecz biorąc, następujący wzór powinien pozwolić ci zrobić to, co próbujesz.
Zauważ, że to działanie aparatu będzie tworzyło i zapisywało plik, a nie jest to w rzeczywistości część twojej aplikacji, więc nie będzie miał uprawnień do zapisu w folderze aplikacji. Aby zapisać plik w folderze aplikacji, utwórz plik tymczasowy na karcie SD i przenieś go do folderu aplikacji w
onActivityResult
module obsługi.źródło
Aby odpowiedzieć na powyższy komentarz Yenchi, przycisk OK również nie zrobi nic, jeśli aplikacja aparatu nie może zapisać w danym katalogu.
Oznacza to, że nie możesz utworzyć pliku w miejscu, które może zapisywać tylko Twoja aplikacja (na przykład coś w sekcji
getCacheDir())
Coś poniżejgetExternalFilesDir()
powinno jednak działać.Byłoby miło, gdyby aplikacja aparatu wydrukowała komunikat o błędzie w dziennikach, gdyby nie mogła zapisać na określonej
EXTRA_OUTPUT
ścieżce, ale jej nie znalazłem.źródło
aby aparat zapisywał na sdcard, ale przechowywać w nowym albumie w aplikacji galerii, której używam:
Pamiętaj, że za każdym razem będziesz musiał wygenerować unikalną nazwę pliku i zastąpić napisany przeze mnie 1111.jpg. Zostało to przetestowane na Nexus One. uri jest zadeklarowany w klasie prywatnej, więc w wyniku działania mogę załadować obraz z uri do imageView w celu wyświetlenia podglądu, jeśli jest to konieczne.
źródło
Miałem ten sam problem i naprawiłem go w następujący sposób:
Problem polega na tym, że kiedy określisz plik, do którego ma dostęp tylko Twoja aplikacja (np. Przez wywołanie
getFileStreamPath("file");
)Dlatego właśnie upewniłem się, że dany plik naprawdę istnieje i KAŻDY ma do niego prawo zapisu.
W ten sposób aplikacja aparatu ma dostęp do zapisu do danego Uri, a przycisk OK działa dobrze :)
źródło
Zalecam śledzenie postu szkoleniowego Androida w celu zrobienia zdjęcia. Pokazują na przykładzie, jak robić małe i duże zdjęcia. Możesz także pobrać kod źródłowy stąd
źródło
Stworzyłem prostą bibliotekę, która będzie zarządzać wyborem obrazów z różnych źródeł (Galeria, Aparat), być może zapisze je w jakimś miejscu (karta SD lub pamięć wewnętrzna) i zwróci obraz, więc proszę go swobodnie używać i ulepszać - Android-ImageChooser .
źródło
Jak zauważył Praveen , aparat musi mieć możliwość zapisu do pliku .
W moim przypadku chciałem przechowywać plik w pamięci wewnętrznej. Zrobiłem to z:
Oto
cacheFile
plik globalny używany w odniesieniu do zapisywanego pliku. Następnie w metodzie wynikowej zwrócona intencja ma wartość null. Wtedy metoda przetwarzania intencji wygląda następująco:Oto
getImageFile()
metoda narzędziowa do nazwania i tworzenia pliku, w którym powinien być przechowywany obraz, icopyFile()
jest to metoda kopiowania pliku.źródło
Możesz użyć tego kodu
źródło
Rozwiązanie tego problemu za pomocą kodu wyniku działania jest bardzo proste. Wypróbuj tę metodę
źródło
źródło