Вопрос или проблема
Я использую Launcher для открытия страницы Facebook из моего приложения следующим образом:
async Task OpenFacebook()
{
try
{
// пытаемся открыть приложение Facebook, если не удалось, пытаемся открыть в браузере
bool opened = await Launcher.Default.TryOpenAsync($"fb://profile?id={FacebookID}");
if (opened)
return;
await Browser.OpenAsync(new Uri($"https://m.facebook.com/{FacebookID}"), BrowserLaunchMode.External);
}
catch (Exception ex)
{
}
}
<activity android:name="com.myapp.MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="fb"/>
</intent-filter>
</activity>
Это работает, когда приложение Facebook установлено, но когда я удаляю приложение, я ожидал, что оно перейдет в браузер и просто откроет URL. На самом деле, оно просто выдает ошибку:
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.myapp/com.myapp.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "com.myapp.MainActivity" on path: DexPathList[[zip file...
, Замечание: opened
возвращает true
, и функция завершается нормально, затем я получаю вышеупомянутое исключение java, которое остается необработанным и вызывает сбой моего приложения. Мне удалось предотвратить сбой, переместив фильтр намерений в MainActivity.cs следующим образом:
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, DataScheme = "fb")]
public class MainActivity : MauiAppCompatActivity
Но теперь, когда я нажимаю кнопку для открытия FB, opened
по-прежнему истинно, и не происходит перехода. Это работает как задумано на iOS, но не на Android. Есть идеи, что я делаю не так?
Ответ или решение
Как обрабатывать попытку запуска внешнего приложения в .NET MAUI для Android, когда приложение не установлено
При разработке приложения на .NET MAUI для Android важно учитывать сценарии, когда внешнее приложение, с которым вы хотите взаимодействовать, может не быть установлено на устройстве пользователя. Одним из таких случаев является попытка открыть приложение Facebook, как это показано в вашем коде. Вы правильно используете Launcher
, чтобы сначала попытаться открыть приложение Facebook, а затем (если оно не установлено) — открыть веб-страницу в браузере. Однако вы столкнулись с проблемой, когда приложение аварийно завершает работу с ошибкой java.lang.RuntimeException
.
Проблема
Когда Facebook не установлен, ваше приложение возвращает true
в результате Launcher.Default.TryOpenAsync
, что не отражает реального состояния (приложение не открывается). Это может происходить из-за того, что Launcher
в фоновом режиме пытается обработать ваше намерение для запуска Facebook, но не находит приложения, что и приводит к сбою.
Решение проблемы
Вам нужно изменить подход к обработке ошибки, чтобы убедиться, что ваш контроллер правильно реагирует на ситуацию, когда Facebook не установлен. Проанализируем возможное решение вашей проблемы.
-
Правильная обработка
TryOpenAsync
:- Давайте посмотрим на то, как вы обрабатываете результат от
TryOpenAsync
. Вместо того чтобы полагаться на возвращаемое значение как на индикатор успешности, проверьте детали выполнения.
- Давайте посмотрим на то, как вы обрабатываете результат от
-
Использование
LaunchError
:- Когда
TryOpenAsync
возвращаетtrue
, это может означать, что намерение было обработано, но не всегда с ожидаемым результатом. Нужно ловить ошибки, возникающие при вызовеTryOpenAsync
, чтобы надёжно обработать сценарии, когда приложение недоступно.
- Когда
-
Использование обработки исключений:
- Если
TryOpenAsync
вызывает исключения, их следует обрабатывать таким образом, чтобы ваш код мог принять решение об открытии браузера. Вот пример:
- Если
async Task OpenFacebook()
{
try
{
// Попробуем открыть приложение Facebook
bool opened = await Launcher.Default.TryOpenAsync($"fb://profile?id={FacebookID}");
if (!opened)
{
// Если не удалось открыть приложение, открываем в браузере
await Browser.OpenAsync(new Uri($"https://m.facebook.com/{FacebookID}"), BrowserLaunchMode.External);
}
}
catch (Exception ex)
{
// Логируем исключение
Console.WriteLine($"Ошибка при открытии Facebook: {ex.Message}");
// Пытаемся открыть Facebook в браузере
await Browser.OpenAsync(new Uri($"https://m.facebook.com/{FacebookID}"), BrowserLaunchMode.External);
}
}
- Обновление вашего IntentFilter:
- Вместо того чтобы размешать
IntentFilter
вMainActivity
, рассмотрите возможность использования его непосредственно в классе, который фактически пытается взаимодействовать с Facebook. Пример:
- Вместо того чтобы размешать
[IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable }, DataScheme = "fb")]
public class FacebookActivity : MauiAppCompatActivity
{
// Ваш код для обработки действия
}
Заключение
Ваша проблема может быть решена путем более тщательной обработки получения результата от Launcher.Default.TryOpenAsync
и правильным использованием try-catch
для исключительных ситуаций. Такой подход обеспечит ваше приложение устойчивостью к ошибкам и улучшит пользовательский опыт. Следуя приведённым рекомендациям, вы сможете плавно обрабатывать ситуации, когда Facebook не установлен, и обеспечивать безошибочное открытие его веб-версии.