Skip to content

Commit 8e8283c

Browse files
committed
android: enable writing stdout/stderr to a socket
This can be done by setting the extra string org.panda3d.OUTPUT_URI to tcp://host:port Writing to a log file can still be done using file:///path/to/log.txt [skip ci]
1 parent 319b331 commit 8e8283c

File tree

3 files changed

+58
-24
lines changed

3 files changed

+58
-24
lines changed

panda/src/android/PandaActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ public String getIntentDataPath() {
8787
return path;
8888
}
8989

90-
public String getIntentOutputPath() {
90+
public String getIntentOutputUri() {
9191
Intent intent = getIntent();
92-
return intent.getStringExtra("org.panda3d.OUTPUT_PATH");
92+
return intent.getStringExtra("org.panda3d.OUTPUT_URI");
9393
}
9494

9595
public String getCacheDirString() {

panda/src/android/android_main.cxx

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717
#include "virtualFileSystem.h"
1818
#include "filename.h"
1919
#include "thread.h"
20+
#include "urlSpec.h"
2021

2122
#include "config_display.h"
2223
// #define OPENGLES_1 #include "config_androiddisplay.h"
2324

2425
#include <android_native_app_glue.h>
26+
#include <sys/socket.h>
27+
#include <arpa/inet.h>
2528

2629
// struct android_app* panda_android_app = NULL;
2730

@@ -67,6 +70,55 @@ void android_main(struct android_app* app) {
6770
android_cat.info()
6871
<< "New native activity started on " << *current_thread << "\n";
6972

73+
// Were we given an optional location to write the stdout/stderr streams?
74+
methodID = env->GetMethodID(activity_class, "getIntentOutputUri", "()Ljava/lang/String;");
75+
jstring joutput_uri = (jstring) env->CallObjectMethod(activity->clazz, methodID);
76+
if (joutput_uri != nullptr) {
77+
const char *output_uri = env->GetStringUTFChars(joutput_uri, nullptr);
78+
79+
if (output_uri != nullptr && output_uri[0] != 0) {
80+
URLSpec spec(output_uri);
81+
82+
if (spec.get_scheme() == "file") {
83+
string path = spec.get_path();
84+
int fd = open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY);
85+
if (fd != -1) {
86+
android_cat.info()
87+
<< "Writing standard output to file " << path << "\n";
88+
89+
dup2(fd, 1);
90+
dup2(fd, 2);
91+
} else {
92+
android_cat.error()
93+
<< "Failed to open output path " << path << "\n";
94+
}
95+
} else if (spec.get_scheme() == "tcp") {
96+
string host = spec.get_server();
97+
int fd = socket(AF_INET, SOCK_STREAM, 0);
98+
struct sockaddr_in serv_addr = {0};
99+
serv_addr.sin_family = AF_INET;
100+
serv_addr.sin_port = htons(spec.get_port());
101+
serv_addr.sin_addr.s_addr = inet_addr(host.c_str());
102+
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
103+
android_cat.info()
104+
<< "Writing standard output to socket "
105+
<< spec.get_server_and_port() << "\n";
106+
dup2(fd, 1);
107+
dup2(fd, 2);
108+
} else {
109+
android_cat.error()
110+
<< "Failed to open output socket "
111+
<< spec.get_server_and_port() << "\n";
112+
}
113+
close(fd);
114+
} else {
115+
android_cat.error()
116+
<< "Unsupported scheme in output URI: " << output_uri << "\n";
117+
}
118+
env->ReleaseStringUTFChars(joutput_uri, output_uri);
119+
}
120+
}
121+
70122
// Fetch the data directory.
71123
jmethodID get_appinfo = env->GetMethodID(activity_class, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
72124

@@ -186,28 +238,6 @@ void android_main(struct android_app* app) {
186238
}
187239
}
188240

189-
// Were we given an optional location to write the stdout/stderr streams?
190-
methodID = env->GetMethodID(activity_class, "getIntentOutputPath", "()Ljava/lang/String;");
191-
jstring joutput_path = (jstring) env->CallObjectMethod(activity->clazz, methodID);
192-
if (joutput_path != nullptr) {
193-
const char *output_path = env->GetStringUTFChars(joutput_path, nullptr);
194-
195-
if (output_path != nullptr && output_path[0] != 0) {
196-
int fd = open(output_path, O_CREAT | O_TRUNC | O_WRONLY);
197-
if (fd != -1) {
198-
android_cat.info()
199-
<< "Writing standard output to file " << output_path << "\n";
200-
201-
dup2(fd, 1);
202-
dup2(fd, 2);
203-
} else {
204-
android_cat.error()
205-
<< "Failed to open output path " << output_path << "\n";
206-
}
207-
env->ReleaseStringUTFChars(joutput_path, output_path);
208-
}
209-
}
210-
211241
// Create bogus argc and argv for calling the main function.
212242
const char *argv[] = {"pview", nullptr, nullptr};
213243
int argc = 1;
@@ -266,6 +296,9 @@ void android_main(struct android_app* app) {
266296
env->ReleaseStringUTFChars(filename, filename_str);
267297
}
268298

299+
close(1);
300+
close(2);
301+
269302
// Detach the thread before exiting.
270303
activity->vm->DetachCurrentThread();
271304
}

panda/src/android/pview_manifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
99
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
10+
<uses-permission android:name="android.permission.INTERNET" />
1011
<uses-sdk android:minSdkVersion="21" />
1112
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
1213

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy