An app's own log: a devlog contract, and a Runtime tab for an APK component
Android forbids one app reading another's logcat, so an APK this server delivers has had no way to say what it did to somebody holding the phone and nothing else. It can now expose its own bounded log through a ContentProvider at `<applicationId>.devlog`, guarded by a permission declared here; README.md's "An app's own log" is the whole contract, and any project this server delivers can implement it. The phone reads that provider while the Runtime tab is open and forwards what is new into the component's runtime log on this machine, so the tab renders from the same store a service's does and the history outlives the phone. `LogKind::Runtime` stays one kind with two sources rather than growing a third, and this server parses nothing -- what arrives is one line of text each, appended, exactly as a service's stdout is. The log button is now unconditional, like the gear beside it: with the tab able to say which of several reasons there is nothing to read, its absence was the one thing that could not say anything at all. Supersedes ai-app posting its ring to ai-server over the tunnel, which put a phone's lines under the wrong component and only ever worked for that one project. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
3727c7c67b
commit
013d7116d7
11 files changed
+772
-44
No files matched your search
@@ -1743,6 +1743,7 @@ private fun AppListScreen(
|
||||
},
|
||||
onRemove = {
|
||||
forgetVariants(context, entry.key)
|
||||
forgetDevLogCursors(context, entry.key)
|
||||
manage(entry, removes = true) {
|
||||
removeApp(entry.key)
|
||||
}
|
||||
@@ -3392,9 +3393,13 @@ private fun ComponentCard(
|
||||
// whatever the text does. Unconditional, so the settings
|
||||
// button sits in the same place whether or not there is a
|
||||
// log beside it -- the log's own absence must not move it.
|
||||
if (component.hasLogs) {
|
||||
IconGlyphButton(LOG_GLYPH, "Show ${component.name}'s log") { showingLog = true }
|
||||
}
|
||||
// Unconditional like the gear beside it, and for the
|
||||
// same reason: a component always has both kinds of log
|
||||
// to ask about, and a button that comes and goes makes
|
||||
// its own absence the answer. There is nothing here yet
|
||||
// and nobody has looked are different things, and the
|
||||
// dialog is where the difference gets said.
|
||||
IconGlyphButton(LOG_GLYPH, "Show ${component.name}'s log") { showingLog = true }
|
||||
// Always drawn, including for a component with a single
|
||||
// build mode and nothing to strip: what a component can be
|
||||
// told is part of what it is, and a control that comes and
|
||||
|
||||
Reference in new issue
Block a user