У меня был аналогичный вопрос, где я хотел только дату, когда была сделана фотография, и ни одна из вышеперечисленных проблем не может решить мою проблему простым способом (например, без внешних библиотек), так что вот все данные, которые я мог бы найти, вы можете извлечь из изображения после выбора его с помощью сборщика:
// Inside whatever implements UIImagePickerControllerDelegate
@import AssetsLibrary;
// ... your other code here ...
@implementation MYImagePickerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
UIImage *originalImage = info[UIImagePickerControllerOriginalImage];
UIImage *editedImage = info[UIImagePickerControllerEditedImage];
NSValue *cropRect = info[UIImagePickerControllerCropRect];
NSURL *mediaUrl = info[UIImagePickerControllerMediaURL];
NSURL *referenceUrl = info[UIImagePickerControllerReferenceURL];
NSDictionary *mediaMetadata = info[UIImagePickerControllerMediaMetadata];
NSLog(@"mediaType=%@", mediaType);
NSLog(@"originalImage=%@", originalImage);
NSLog(@"editedImage=%@", editedImage);
NSLog(@"cropRect=%@", cropRect);
NSLog(@"mediaUrl=%@", mediaUrl);
NSLog(@"referenceUrl=%@", referenceUrl);
NSLog(@"mediaMetadata=%@", mediaMetadata);
if (!referenceUrl) {
NSLog(@"Media did not have reference URL.");
} else {
ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
[assetsLib assetForURL:referenceUrl
resultBlock:^(ALAsset *asset) {
NSString *type =
[asset valueForProperty:ALAssetPropertyType];
CLLocation *location =
[asset valueForProperty:ALAssetPropertyLocation];
NSNumber *duration =
[asset valueForProperty:ALAssetPropertyDuration];
NSNumber *orientation =
[asset valueForProperty:ALAssetPropertyOrientation];
NSDate *date =
[asset valueForProperty:ALAssetPropertyDate];
NSArray *representations =
[asset valueForProperty:ALAssetPropertyRepresentations];
NSDictionary *urls =
[asset valueForProperty:ALAssetPropertyURLs];
NSURL *assetUrl =
[asset valueForProperty:ALAssetPropertyAssetURL];
NSLog(@"type=%@", type);
NSLog(@"location=%@", location);
NSLog(@"duration=%@", duration);
NSLog(@"assetUrl=%@", assetUrl);
NSLog(@"orientation=%@", orientation);
NSLog(@"date=%@", date);
NSLog(@"representations=%@", representations);
NSLog(@"urls=%@", urls);
}
failureBlock:^(NSError *error) {
NSLog(@"Failed to get asset: %@", error);
}];
}
[picker dismissViewControllerAnimated:YES
completion:nil];
}
@end
Поэтому, когда вы выбираете изображение, вы получаете вывод, который выглядит так (включая дату!):
mediaType=public.image
originalImage=<UIImage: 0x7fb38e00e870> size {1280, 850} orientation 0 scale 1.000000
editedImage=<UIImage: 0x7fb38e09e1e0> size {640, 424} orientation 0 scale 1.000000
cropRect=NSRect: {{0, 0}, {1280, 848}}
mediaUrl=(null)
referenceUrl=assets-library://asset/asset.JPG?id=AC072879-DA36-4A56-8A04-4D467C878877&ext=JPG
mediaMetadata=(null)
type=ALAssetTypePhoto
location=(null)
duration=ALErrorInvalidProperty
assetUrl=assets-library://asset/asset.JPG?id=AC072879-DA36-4A56-8A04-4D467C878877&ext=JPG
orientation=0
date=2014-07-14 04:28:18 +0000
representations=(
"public.jpeg"
)
urls={
"public.jpeg" = "assets-library://asset/asset.JPG?id=AC072879-DA36-4A56-8A04-4D467C878877&ext=JPG";
}
В любом случае, надеюсь, что кто-то еще кого-нибудь спасет.
Ничто из этого не легко реализовать и не будет функционировать оптимальным образом.
Фрагменты имеют вызов метода onDetach, который выполнит эту работу.
@Override
public void onDetach() {
super.onDetach();
PUT YOUR CODE HERE
}
ЭТО ДЕЛАЕТ РАБОТУ.
Если вы используете EventBus, это, вероятно, гораздо более простое решение:
В вашем фрагменте:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
EventBus.getDefault().register(this);
}
@Override
public void onDetach() {
super.onDetach();
EventBus.getDefault().unregister(this);
}
// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
getSupportFragmentManager().popBackStack();
}
и в вашем классе деятельности вы можете определить :
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
super.onBackPressed();
}
@Override
public void onBackPressed() {
EventBus.getDefault().post(new BackPressedMessage(true));
}
BackPressedMessage.java - это просто объект POJO
Это очень чисто и нет проблем с интерфейсом / реализацией.
Если Вы используете androidx.appcompat:appcompat:1.1.0
, или выше затем Вас может добавить OnBackPressedCallback
к Вашему фрагменту следующим образом
requireActivity()
.onBackPressedDispatcher
.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Log.d(TAG, "Fragment back pressed invoked")
// Do custom work here
// if you want onBackPressed() to be called as normal afterwards
if (isEnabled) {
isEnabled = false
requireActivity().onBackPressed()
}
}
}
)
, См. https://developer.android.com/guide/navigation/navigation-custom-back
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}
Просто Комментарий Любой Ключ вниз имел отношение, метод теперь addToBackStack будет работать. спасибо
Необходимо переопределить onBackPressed () со слушателем фрагмента. Вот то, как:
В моем решении (Kotlin);
я использую функцию onBackAlternative в качестве параметра на [1 111] BaseActivity.
BaseActivity
abstract class BaseActivity {
var onBackPressAlternative: (() -> Unit)? = null
override fun onBackPressed() {
if (onBackPressAlternative != null) {
onBackPressAlternative!!()
} else {
super.onBackPressed()
}
}
}
у меня есть функция для набора onBackPressAlternative на [1 113] BaseFragment.
BaseFragment
abstract class BaseFragment {
override fun onStart() {
super.onStart()
...
setOnBackPressed(null) // Add this
}
fun setOnBackPressed(onBackAlternative: (() -> Unit)?) {
(activity as BaseActivity<*, *>).onBackPressAlternative = onBackAlternative
}
}
Затем мой onBackPressAlternative готов использовать на фрагментах.
Фрагменты Sub
class LoginFragment : BaseFragment {
override fun onStart() {
super.onStart()
...
setOnBackPressed {
// Finally, you can write your custom onBackPressed function to here
}
}
}
Обеспечение пользовательской задней навигации путем обработки onBackPressed теперь более легко с обратными вызовами во фрагменте.
class MyFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (true == conditionForCustomAction) {
myCustomActionHere()
} else NavHostFragment.findNavController(this@MyFragment).navigateUp();
}
}
requireActivity().onBackPressedDispatcher.addCallback(
this, onBackPressedCallback
)
...
}
, Если Вы хотите обратное действие по умолчанию на основе некоторого условия, можно использовать:
NavHostFragment.findNavController(this@MyFragment).navigateUp();