I have the following in my AndroidManifest.xml (I just added a second activity to the default project):
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.com.testapp.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>
<activity
android:name="com.example.com.testapp.TestActivity"
android:label="@string/title_activity_test" >
<intent-filter>
<action android:name="com.testapp.action.TEST_ACTION" />
</intent-filter>
</activity>
I want to launch the TestActivity using adb command. I tried:
./adb shell am start -a com.testapp.action.TEST_ACTION
But it gives the error:
Error: Activity not started, unable to resolve Intent { act=com.testapp.action.TEST_ACTION flg=0x10000000 }
Can someone please explain why I am getting this error and how to resolve it?
Edit :
Can anyone tell a way to just use action to launch the ‘TestActivity’.
asked Mar 31, 2014 at 17:05
JakeJake
16k48 gold badges121 silver badges200 bronze badges
I think you should add the code below into your intentfilter
<category android:name="android.intent.category.DEFAULT"/>
answered Mar 16, 2017 at 3:31
陈薛星陈薛星
761 silver badge3 bronze badges
try using:
adb shell "am start -n com.example.com.testapp/.TestActivity -a com.testapp.action.TEST_ACTION"
or
adb shell "am start com.example.com.testapp -a com.testapp.action.TEST_ACTION"
hope that works.
answered Mar 31, 2014 at 17:13
The BadakThe Badak
2,0002 gold badges15 silver badges28 bronze badges
3
Try adb shell am start -n com.mypackage.name/com.mypackage.name.TEST_ACTION
(replace the package names and activity names as needed)
Take a look at this solution.
answered Mar 31, 2014 at 17:13
FMontanoFMontano
8578 silver badges16 bronze badges
To expand on what 陈薛星 wrote, in the «Android developer guide on Intent Filters» under «Category Test», it states
Note: Android automatically applies the CATEGORY_DEFAULT category to all implicit intents passed to startActivity() and startActivityForResult(). If you want your activity to receive implicit intents, it must include a category for «android.intent.category.DEFAULT» in its intent filters, as shown in the previous example.
So you need to add
<category android:name="android.intent.category.DEFAULT"/>
to your intent filter.
This will match an implicit intent. (Several other answers show how to target a class explicity).
answered Aug 31, 2018 at 6:54
HodHod
2,2261 gold badge14 silver badges22 bronze badges
I keep having an error trying to start some apps using am start command. It works for many, but for some apps I get the same error mentioned below:
#adb shell am start com.amazon.venezia Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=com.amazon.venezia } Error: Activity not started, unable to resolve Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=com.amazon.venezia } #adb shell am start com.whatsapp Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] pkg=com.whatsapp } Error: Activity not started, unable to resolve Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 pkg=com.whatsapp }
Firelord♦
24k19 gold badges117 silver badges268 bronze badges
asked Mar 9, 2016 at 20:29
11
use this:
adb shell am start -n com.whatsapp/.HomeActivity
Dan Hulme
34.6k17 gold badges88 silver badges152 bronze badges
answered Apr 7, 2016 at 12:40
Gbla KblaGbla Kbla
611 silver badge2 bronze badges
1
You must log in to answer this question.
Not the answer you’re looking for? Browse other questions tagged
.
Not the answer you’re looking for? Browse other questions tagged
.
Время прочтения
8 мин
Просмотры 1.1K
Введение
Раз, два, три, четыре! В прошлый раз мы выяснили вот что
Гипотеза 3. Разные оболочки ОС — ОПРОВЕРГНУТА.
Оболочка Android ОС НЕ ВЛИЯЕТ на работу Deep Link
Гипотеза 4. Приложения — ПОДТВЕРЖДЕНА.
Приложение, из которого открывается ссылка, ВЛИЯЕТ на работу Deep Link.
Как обычно не обошлось без тонкостей: оболочка может влиять на обработку, но через свои (специфичные для оболочки) приложения. У приложений есть встроенные браузеры, но даже они не повлияли на однозначный вывод – приложения влияют на работу deep link.
Сегодня мы завершаем разбор наших семи проблем. Наконец-то! Набирайте кислород. Погружаемся!
Содержание
-
Введение
-
Проблема №5. Ссылки без scheme
-
Обработка scheme приложением
-
Проблема №6. Второй host
-
Проблема №7. Перехват всех ссылок
-
Резюме
Проблема №5. Ссылки без scheme
Ссылки вида host/path обрабатывались по-разному
Одна и та же ссылка, одно и то же устройство, но разные приложения (Messaging, Gmail):
Теперь эксперименты:
Мы уже знаем, что приложение влияет на обработку deep link. Но мы еще не пробовали переходить по ссылкам без host. Как видно выше переход по ссылке возможен, даже несмотря на отсутствие host. Предположим:
Гипотеза 5. Существует специальный механизм обработки ссылок без scheme.
Может появиться ощущение, что если прописать в манифесте схему null
, то ссылки без схемы будут работать. Давайте попробуем
Есть еще один способ тестировать deep link, помимо ручного клика по ссылкам. Для этого нужно вызвать команду adb:
adb shell am start -W -d null:developer.android.com
Эта команда запустит intent с указанным Data URI (-d
) и будет ожидать завершения запуска (-W
).
Если настроить соответствующий intent-filter, то ОС сможет понять может ли ваше приложение обработать этот intent. Мы так и сделали. Теперь давайте посмотрим на скринкаст:
На заднем фоне видно, как наше приложение запустилось. Это значит, что
android:scheme=»null» — это конкретное значение scheme, а не ее отсутствие.
Если null это не значит отсутствие scheme, то может вообще ее не указывать? Интересное предположение. Настраиваем intent-filter:
Студия подсказывает, что мы не указали обязательный атрибут scheme. Но не смотря на это скомпилировать получится.
Попробуем запустить intent через adb, но в этот раз без scheme:
adb shell am start -W -d developer.android.com
В консоли видим:
Starting: Intent { dat=developer.android.com/about }
Error: Activity not started, unable to resolve Intent { dat=developer.android.com/about flg=0x10000000 }
Intent resolution не завершился успехом, даже не смотря на настроенный intent-filter. Давайте кликнем на ссылку:
Обратимся к документации. Там написано, что, как минимум, нужно прописать хотя бы одну схему для интент-фильтра, иначе ни один другой атрибут не будет обработан (схожее сообщение мы видели в студии):
“…at least one scheme attribute must be set for the filter,
or none of the other URI attributes are meaningful.”
— А что если написать android:scheme=””
?
— Будет тоже самое, что и для только что разобранного примера.
После нескольких попыток у нас появилось предположение, что на обработку влияет http. Это оказалось действительно так. Посмотрите, что происходит на записи:
Давайте посмотрим на нечто более убедительное. Открываем logcat:
I/ActivityTaskManager: START u0 {
act=android.intent.action.VIEW
dat=http://developer.android.com/about
flg=0x14002000 cmp=com.android.chrome/
org.chromium.chrome.browser.ChromeTabbedActivity
(has extras)
} from uid 10116
Здесь уже не остается никаких вопросов. http scheme была подставлена в URL без scheme. Причем это сделало именно приложение, а не мы или что-либо еще! Это в очередной раз доказывает, насколько сильно приложение, из которого открывается ссылка, влияет на работу deep link. Но как так получилось? Узнаем дальше.
Обработка scheme приложением
Кажется, что developer.android.com/about как-то сам сумел превратиться в ссылку. Так ли это на самом деле? Проверить просто: добавим TextView
на экран и в android:text
укажем три вида ссылок:
Никакой магии не случилось. Ссылки не стали кликабельными. Все потому, что не настроен специальный обработчик.
В Android есть много способов обработать URL (и scheme, в частности):
Рассмотрим каждый подробнее на примере. Дано:
android:autoLink
Начнём с самого лаконичного способа. Атрибут android:autoLink
запускает поиск паттернов по содержимому TextView. Среди паттернов для поиска есть email, phone, map
. Константа web
, выполняет поиск URL’ов. То, что там нужно.
Добавляем autoLink c значением web в TextView:
Запускаем. Видим, что ссылка стала кликабельной. Более того, по клику запускается интент, где в data лежит URL с автоматически проставленной http схемой. Красота!
android.text.util.Linkify.addLinks
Эта статическая функция применяет регулярное выражение к содержимому TextView и выполняет поиск соответствий. Похоже на работу autoLink. В качестве аргумента addLinks
можно передать defaultScheme
, которая будет приставлена к ссылке, если та не начинается со схемы, указанной в другом параметре.
Вызываем addLinks
и передаем нашу TextView, Pattern
для WEB URL, дефолтную схему https, стандартный UrlMatchFilter
, и null TransformFilter
.
Запускаем. Результат как и в прошлом примере, но только в этот раз была подставлена https scheme.
android.text.util.Linkify.TransformFilter
Та же функция addLinks
, но в этот раз используется параметр transformFilter
, который позволяет изменять найденные ссылки.
В этот раз defaultScheme
равны null
, а в качестве transformFilter
выступает наш HttpsTransformFilter
, который добавляет префикс к URL.
Запускаем. Результат такой же, как и в прошлом примере.
android.text.Html
Если в приложении есть работа с HTML тегами, то этот способ может быть кстати. Воспользуемся статической функцией fromHtml и классом LinkMovementMethod.
fromHtml
из html-тега возвращает отображаемый текст и устанавливает ему ссылку из атрибута href
. LinkMovementMethod представит переданный ему текст как кликабельную ссылку.
Запускаем. Ссылка без scheme превратилась в кликабельную и указывает на https-ссылку.
android.text.style.URLSpan
Теперь посмотрим на механизм, который лежит в основе большинства разобранных способов обработки — spannable.
Интерфейс Spanned позволяет добавлять разметку к тексту. Одним из видов Span является URLSpan, который преобразует выбранный текст в кликабельный. По клику на URLSpan запускается Intent с ACTION_VIEW. Фильтр на этот aciton мы настраивали в нашем приложении.
Во ViewModel
мы создали SpannableString
, передали ссылку без схемы, добавили URLSpan
, указали необходимую ссылку. Так как SpannableString
не является наследником String, то меняем тип данных на CharSequence
. Обратите внимание на LinkMovementMethod
. Он триггерит запуск интента по ссылке из URLSpan
.
Запускаем. Работает как часы!
Мы разобрали три наиболее распространенных способов обработки ссылок. Есть и другие (например, Better-Link-Movement-Method), но они, как правило, используют разобранные нами API.
Все еще помните, о какой гипотезе шла речь? Мы проделали большую работу и смело можем заключить:
Гипотеза 5 — ПОДТВЕРЖДЕНА.
Существует специальный механизм обработки ссылок без scheme.
Проблема №6. Второй host
Мы забыли о том, что у нас есть второй домен.
У нашего проекта два хоста: один из них основной, а другой редиректит на основной. Нам заранее неизвестно, по какому из них пользователь перейдет в наше приложение. При этом рабочими должны быть оба варианта.
Сначала мы думали, что можно прописать для каждого хоста свой интент-фильтр:
Потом вспомнили, что по итогам все data-теги из одного фильтра, смерджатся и будут созданы всевозможные комбинации из их атрибутов. Не стоит забывать об этой особенности, потому что она может привести к неожиданным последствиям
Мы решили не поддерживать два отдельных intent-filter и переписали предыдущий код. Получилось сильно короче и проще.
Проблема №7. Перехват всех ссылок
Приложение начало перехватывать все ссылки с нашим доменом
(даже те, для которых у нас не было сценариев обработки)
Есть два ресурса: privacy-policy и terms-of-use. Подразумевается, что пользователь будет обращаться к ним через браузер (на эти ссылки мы явно не настраивали deep link). В нашем приложении нет экранов для отображения этого контента. Но как вы можете видеть на скринкасте, при переходе по ссылкам система предлагает открыть наше приложение. У нас этого контента нет, поэтому пользователь видит 404. Знатоки, внимание: вопрос: “Почему так случилось?”.
Изначально мы хотели добавить диплинки на ссылки без path. То есть ссылки, у которых есть только схема и хост (например, http://developer.android.com). Для этого мы настроили наш intent-filter так:
После этого ссылки без path начали обрабатываться нашим приложением. Это поведение мы и хотели получить. Ссылки на существующий контент также обрабатывались нашим приложением. Все как надо.
Но помимо этого появилась обработка ссылок с path на несуществующий контент, что вело к появлению 404 ошибок. Дело в том, что
Отсутствие явно указанного path подразумевает использование любого значения.
Чтобы избавиться от нежелательного поведения, нам пришлось отказаться от обработки ссылок без path. Иначе нам пришлось бы обрабатывать всевозможные вариации путей. В тот момент мы не были к этому готовы да и особой надобности в этом не было.
Резюме
Фух! Много нового в этот раз:
-
Гипотеза 5 — Подтверждена. Существует специальный механизм обработки ссылок без scheme.
-
Для тестирования deep link иногда удобно пользоваться командой: adb shell am start -W -d “Data URI”.
-
android:scheme=»null» — это конкретное значение scheme, а не ее отсутствие.
-
android:scheme=»» или отсутствие этого атрибута приведет к тому, что ни один другой атрибут не будет обработан и deep link работать не будет.
-
android:autoLink — короткий и простой способ сделать URL кликабельной ссылкой.
-
Linkify.addLinks функция, которая применяет регулярное выражение к содержимому TextView и выполняет поиск соответствий и имеет параметры для обработки.
-
android.text.Html.fromHtml преобразует html-теги в Spanned, URLSpan в частности.
-
android.text.style.URLSpan специальный вид span, который преобразует текст в кликабельный и запускает intent с ACTION_VIEW и Data URL по клику.
-
android.text.method.LinkMovementMethod обрабатывает нажатие по тексту-ссылке.
-
Data-теги мерджатся между собой. По итогу получаются всевозможные комбинации из значений. Например: http, https, host1, host2 преобразуются в http://host1, http://host2, https://host1, https://host2.
-
Аккуратнее с ссылками без path: его отсутствие в <data /> понимается ОС как возможность передавать любое значение. Ваше приложение может начать обрабатывать то, что не должно.
На сегодня это все. В заключительной части серии мы разберем несколько суперважных нюансов:
-
Почему path паттерны такие слабые?
-
Как происходит диспетчеризация URL?
-
Почему Jetpack Navigation Component не так крут, как кажется?
-
Как мы кастомизировали обработку deep link.
-
И почему очень важно помнить про обратную совместимость deep link.
Скоро увидимся!
Валера Петров
Android-разработчик. TG: @valeryvpetrov
Ангелина Евсикова
Android-разработчица Технократии. TG: @Angelina_dev
Также подписывайтесь на наш телеграм-канал «Голос Технократии». Каждое утро мы публикуем новостной дайджест из мира ИТ, а по вечерам делимся интересными и полезными мастридами.
У меня есть следующее в моем AndroidManifest.xml (я просто добавил второй проект к проекту по умолчанию):
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.com.testapp.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>
<activity
android:name="com.example.com.testapp.TestActivity"
android:label="@string/title_activity_test" >
<intent-filter>
<action android:name="com.testapp.action.TEST_ACTION" />
</intent-filter>
</activity>
Я хочу запустить TestActivity, используя команду adb. Я пытался:
./adb shell am start -a com.testapp.action.TEST_ACTION
Но это дает ошибку:
Error: Activity not started, unable to resolve Intent { act=com.testapp.action.TEST_ACTION flg=0x10000000 }
Может кто-нибудь объяснить, почему я получаю эту ошибку и как ее решить?
Редактировать:
Может кто-нибудь сказать, как просто использовать действие для запуска «TestActivity».
- Remove From My Forums
-
Question
-
User151404 posted
Hi Everyone,
I’d like to invoke an intent from Chrome (Android). I know this is possible because I can invoke zxing using the follow HTML snippet:
<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end"> Take a QR code </a>
This works perfectly. After tapping the «Take a QR code» link in a web page the zxing app opens up. The problem is, I can’t seem to get my Xamarin code set up correctly to get my own app to be invoked; everytime I tap the link for my own app it tries to open the Play Store and a «not found» message pops up because this app isn’t in the Play Store.
Does anyone have a sample project they can share that is already set up and working? Perhaps I’m not getting the intent link set up correctly or maybe I don’t have the right intent-filter in my app. I’d just like to start from something that is working and then try to figure out where I went wrong.
Thanks,
Jeff