diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index de3dbbab..ad2b8849 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -63,7 +63,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -75,6 +114,7 @@
+
diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java
index ef721874..5936c34b 100644
--- a/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java
+++ b/android/src/ca/openprivacy/cwtch/ui/CwtchActivity.java
@@ -1,11 +1,13 @@
-package ca.openprivcy.cwtch.ui;
+package ca.openprivacy.cwtch.ui;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.content.Context;
import android.content.Intent;
-
+import android.util.Log;
+import android.os.Bundle;
+import android.content.ComponentName;
import static android.app.Notification.DEFAULT_LIGHTS;
import static android.app.Notification.DEFAULT_SOUND;
@@ -16,7 +18,7 @@ import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
-import static android.app.Notification.CATEGORY_SERVICE;SS
+import static android.app.Notification.CATEGORY_SERVICE;
public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
@@ -37,12 +39,22 @@ public class CwtchActivity extends org.qtproject.qt5.android.bindings.QtActivity
private static String CONTENT_NOTIFICATION_ID_NAME = "content";
- public CwtchActivity()
- {
+ public CwtchActivity() {
m_instance = this;
+ }
- /*Intent intent = new Intent(this, CwtchService.class);
- startService(intent);*/
+ // https://github.com/bbernhard/qtandroidservices_example/blob/master/source/java/MyCustomAppActivity.java
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ Log.i("CwtchActivity", "Starting service!");
+ Intent serviceIntent = new Intent(this, ca.openprivacy.cwtch.ui.CwtchService.class);
+ ComponentName ret = startService(serviceIntent);
+ if (ret == null) {
+ Log.i("CwtchActivity", "Started Service: FAILED with null");
+ } else {
+ Log.i("CwtchActivity", "Started Service: " + ret.flattenToString());
+ }
}
public static void notify(String s)
diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java b/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java
deleted file mode 100644
index 411ac359..00000000
--- a/android/src/ca/openprivacy/cwtch/ui/CwtchIntentService.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package ca.openprivcy.cwtch.ui;
-
-import android.app.IntentService;
-import android.content.Intent;
-import android.util.Log;
-
-public class CwtchIntentService extends IntentService {
-
- /**
- * A constructor is required, and must call the super IntentService(String)
- * constructor with a name for the worker thread.
- */
- public CwtchIntentService() {
- super("CwtchIntentService");
- }
-
- /**
- * The IntentService calls this method from the default worker thread with
- * the intent that started the service. When this method returns, IntentService
- * stops the service, as appropriate.
- */
- @Override
- protected void onHandleIntent(Intent intent) {
- // Normally we would do some work here, like download a file.
- // For our sample, we just sleep for 5 seconds.
- try {
- Log.i("CwtchIntentService", "onHandleIntent!!!!!!");
- } catch (Exception e) { //InterruptedException e) {
- // Restore interrupt status.
- Thread.currentThread().interrupt();
- }
- }
-}
-
diff --git a/android/src/ca/openprivacy/cwtch/ui/CwtchService.java b/android/src/ca/openprivacy/cwtch/ui/CwtchService.java
new file mode 100644
index 00000000..13601b45
--- /dev/null
+++ b/android/src/ca/openprivacy/cwtch/ui/CwtchService.java
@@ -0,0 +1,15 @@
+package ca.openprivacy.cwtch.ui;
+
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.util.Log;
+import android.content.Context;
+import android.content.Intent;
+import org.qtproject.qt5.android.bindings.QtService;
+
+// https://github.com/bbernhard/qtandroidservices_example
+public class CwtchService extends QtService {
+
+}
+
diff --git a/android/src/ca/openprivacy/cwtch/ui/Runnable.java b/android/src/ca/openprivacy/cwtch/ui/Runnable.java
deleted file mode 100644
index dfda506e..00000000
--- a/android/src/ca/openprivacy/cwtch/ui/Runnable.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ca.openprivcy.cwtch.ui;
-
-public class Runnable implements java.lang.Runnable {
- static {
- System.loadLibrary("go");
- }
- public String ObjectName;
-
- public static native void qtrun(qt.java.lang.Runnable me);
- @Override
- public void run() {
- qtrun(this);
- }
-}
\ No newline at end of file
diff --git a/go/gothings/android/CwtchService.go b/go/gothings/android/CwtchService.go
deleted file mode 100644
index a6034423..00000000
--- a/go/gothings/android/CwtchService.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package android
-
-import (
- "git.openprivacy.ca/openprivacy/libricochet-go/log"
- "github.com/therecipe/qt/androidextras"
- "time"
-)
-
-type CwtchService struct {
- androidextras.QAndroidService
- //core.QObject
-
- //_ func() `constructor:"init"`
-}
-
-func (cs *CwtchService) onCreate() {
- log.Infof("CwtchService onCreate()\n")
-
- go func() {
- i := 0
- for true {
- time.Sleep(2 * time.Second)
- log.Infof("CwtchService thread iteration %d\n", i)
- i++
- }
- }()
-}
diff --git a/go/gothings/android/runnable.go b/go/gothings/android/runnable.go
deleted file mode 100644
index 6ad133a2..00000000
--- a/go/gothings/android/runnable.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package android
-
-import "C"
-import (
- "unsafe"
-
- "github.com/therecipe/qt"
- "github.com/therecipe/qt/androidextras"
-)
-
-type Runnable struct {
- ptr *androidextras.QAndroidJniObject
-}
-
-type Runnable_ITF interface {
- Runnable_PTR() *Runnable
-}
-
-func (p *Runnable) Pointer() *androidextras.QAndroidJniObject {
- return p.ptr
-}
-
-func (p *Runnable) SetPointer(ptr *androidextras.QAndroidJniObject) {
- p.ptr = ptr
-}
-
-func (ptr *Runnable) ConnectRun(f func()) {
- if ptr.Pointer() != nil && ptr.Pointer().IsValid() {
-
- qt.ConnectSignal(ptr.Pointer().ToString(), "Runnable::run", unsafe.Pointer(&f))
- }
-}
-
-func (ptr *Runnable) DisconnectRun() {
- if ptr.Pointer() != nil && ptr.Pointer().IsValid() {
-
- qt.DisconnectSignal(ptr.Pointer().ToString(), "Runnable::run")
- }
-}
-
-//export Java_qt_java_lang_Runnable_qtrun
-func Java_qt_java_lang_Runnable_qtrun(_, _, this unsafe.Pointer) {
- if signal := qt.GetSignal(androidextras.NewQAndroidJniObject6(this).ToString(), "Runnable::run"); signal != nil {
- (*(*func())(signal))()
- }
-
-}
-
-func (ptr *Runnable) Run() {
- if ptr.Pointer() != nil && ptr.Pointer().IsValid() {
- ptr.Pointer().CallMethodVoid2("run", "()V")
- }
-}
-
-func PointerFromRunnable(ptr Runnable_ITF) *androidextras.QAndroidJniObject {
- if ptr != nil {
- return ptr.Runnable_PTR().Pointer()
- }
- return nil
-}
-
-func NewRunnableFromPointer(ptr androidextras.QAndroidJniObject_ITF) *Runnable {
- var n = new(Runnable)
- n.SetPointer(ptr.QAndroidJniObject_PTR())
- return n
-}
-
-func (ptr *Runnable) Runnable_PTR() *Runnable {
- return ptr
-}
-
-func Runnable__IsClassAvailable() bool {
- return androidextras.QAndroidJniObject_IsClassAvailable("java/lang/Runnable")
-}
-
-func Runnable__IsQtClassAvailable() bool {
- return androidextras.QAndroidJniObject_IsClassAvailable("qt/java/lang/Runnable")
-}
-
-func (ptr *Runnable) SetObjectName(n string) {
- if ptr.Pointer() != nil && ptr.Pointer().IsValid() {
- ptr.Pointer().SetField2("ObjectName", "Ljava/lang/String;", n)
- }
-}
-
-func (ptr *Runnable) ObjectName() string {
- if ptr.Pointer() != nil && ptr.Pointer().IsValid() {
- return ptr.Pointer().GetObjectField2("ObjectName", "Ljava/lang/String;").ToString()
- }
- return ""
-}
-
-func NewQtRunnable() *Runnable {
- return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("qt/java/lang/Runnable", "()V"))
-}
-func NewRunnable() *Runnable {
- return NewRunnableFromPointer(androidextras.NewQAndroidJniObject3("java/lang/Runnable", "()V"))
-}
diff --git a/main.go b/main.go
index 3de0ec4e..15f9f2b6 100644
--- a/main.go
+++ b/main.go
@@ -21,6 +21,7 @@ import (
"path"
"path/filepath"
"runtime"
+ "time"
)
const androidBaseDir = "/data/data/ca.openprivacy.cwtch.ui/"
@@ -36,8 +37,10 @@ func init() {
}
func main() {
+ log.Infoln("ui main()\n")
flagDebug := flag.Bool("debug", false, "turn on extra logging. WARNING: THIS MAY EXPOSE PRIVATE INFORMATION IN CONSOLE OUTPUT!")
flagLocal := flag.Bool("local", false, "load user interface from the local folder \"qml\" instead of the built-in UI")
+ flagService := flag.Bool("service", false, "indicate this process should run as an android service")
flag.Parse()
if *flagDebug {
@@ -46,83 +49,113 @@ func main() {
log.SetLevel(log.LevelInfo)
}
- // our globals
- gcd := gothings.NewGrandCentralDispatcher(nil)
- gcd.SetOs(runtime.GOOS)
- if buildVer != "" {
- gcd.SetVersion(buildVer)
- gcd.SetBuildDate(buildDate)
+ log.Infof("cwtch main args: %v\n", os.Args)
+
+ if *flagService {
+ log.Infoln("I am the service")
+ torpath := path.Join(androidBaseDir, "lib/libtor.so")
+ log.Infoln("Starting Tor...")
+ acn, _ := connectivity.StartTor(the.CwtchDir, torpath)
+ log.Infoln("Starting a cwtch app...")
+ the.CwtchApp = libapp.NewApp(acn, the.CwtchDir)
+
+ log.Infoln("Sleepinging???")
+ for true {
+ time.Sleep(5 * time.Second)
+ log.Infoln("Wake up, repeat")
+ }
+
} else {
- gcd.SetVersion("development")
- gcd.SetBuildDate("now")
- }
- gcd.UIState = gothings.NewUIState(gcd)
- the.AcknowledgementIDs = make(map[string][]*the.AckId)
- gcd.OutgoingMessages = make(chan gobjects.Letter, 1000)
+ log.Infoln("I am the application")
- //TODO: put theme stuff somewhere better
- gcd.SetThemeScale(1.0)
+ app := gui.NewQGuiApplication(len(os.Args), os.Args)
- // this is to load local qml files quickly when developing
- var qmlSource *core.QUrl
- if *flagLocal {
- qmlSource = core.QUrl_FromLocalFile("./qml/main.qml")
- } else {
- qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0)
- }
+ // our globals
+ gcd := gothings.NewGrandCentralDispatcher(nil)
+ gcd.SetOs(runtime.GOOS)
+ if buildVer != "" {
+ gcd.SetVersion(buildVer)
+ gcd.SetBuildDate(buildDate)
+ } else {
+ gcd.SetVersion("development")
+ gcd.SetBuildDate("now")
+ }
+ gcd.UIState = gothings.NewUIState(gcd)
+ the.AcknowledgementIDs = make(map[string][]*the.AckId)
+ gcd.OutgoingMessages = make(chan gobjects.Letter, 1000)
- app := gui.NewQGuiApplication(len(os.Args), os.Args)
- app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png"))
-
- // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings
- translator := core.NewQTranslator(nil)
- translator.Load("translation_en", ":/i18n/", "", "")
- core.QCoreApplication_InstallTranslator(translator)
-
- gcd.Translator = core.NewQTranslator(nil)
- gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "")
- core.QCoreApplication_InstallTranslator(gcd.Translator)
-
- core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
- quickcontrols2.QQuickStyle_SetStyle("Universe")
- engine := qml.NewQQmlApplicationEngine(nil)
- gcd.QMLEngine = engine
-
- // prevent qt from initiating network connections (possible deanon attempts!)
- factory := qml.NewQQmlNetworkAccessManagerFactory()
- factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager {
- nam := network.NewQNetworkAccessManager(parent)
- nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible)
- proxy := network.NewQNetworkProxy()
- proxy.SetHostName("0.0.0.0")
- nam.SetProxy(proxy)
- //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply {
- // log.Errorf("network access request detected - possible remote content insertion bug!!!")
- // return nil
- //})
- return nam
- })
- engine.SetNetworkAccessManagerFactory(factory)
-
- // variables we want to access from inside qml
- if runtime.GOOS == "android" {
- gcd.SetThemeScale(2.9)
- } else {
+ //TODO: put theme stuff somewhere better
gcd.SetThemeScale(1.0)
+
+ // this is to load local qml files quickly when developing
+ var qmlSource *core.QUrl
+ if *flagLocal {
+ qmlSource = core.QUrl_FromLocalFile("./qml/main.qml")
+ } else {
+ qmlSource = core.NewQUrl3("qrc:/qml/main.qml", 0)
+ }
+
+ app.SetWindowIcon(gui.NewQIcon5(":/qml/images/cwtch-icon.png"))
+
+ // load english first so it becomes the default in case we don't have a .ts for the user's locale, or if it contains unfinished strings
+ translator := core.NewQTranslator(nil)
+ translator.Load("translation_en", ":/i18n/", "", "")
+ core.QCoreApplication_InstallTranslator(translator)
+
+ gcd.Translator = core.NewQTranslator(nil)
+ gcd.Translator.Load("translation_"+core.QLocale_System().Name(), ":/i18n/", "", "")
+ core.QCoreApplication_InstallTranslator(gcd.Translator)
+
+ core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
+ quickcontrols2.QQuickStyle_SetStyle("Universe")
+ engine := qml.NewQQmlApplicationEngine(nil)
+ gcd.QMLEngine = engine
+
+ // prevent qt from initiating network connections (possible deanon attempts!)
+ factory := qml.NewQQmlNetworkAccessManagerFactory()
+ factory.ConnectCreate(func(parent *core.QObject) *network.QNetworkAccessManager {
+ nam := network.NewQNetworkAccessManager(parent)
+ nam.SetNetworkAccessible(network.QNetworkAccessManager__NotAccessible)
+ proxy := network.NewQNetworkProxy()
+ proxy.SetHostName("0.0.0.0")
+ nam.SetProxy(proxy)
+ //nam.ConnectCreateRequest(func(op network.QNetworkAccessManager__Operation, originalReq *network.QNetworkRequest, outgoingData *core.QIODevice) *network.QNetworkReply {
+ // log.Errorf("network access request detected - possible remote content insertion bug!!!")
+ // return nil
+ //})
+ return nam
+ })
+ engine.SetNetworkAccessManagerFactory(factory)
+
+ // variables we want to access from inside qml
+ if runtime.GOOS == "android" {
+ gcd.SetThemeScale(2.9)
+ } else {
+ gcd.SetThemeScale(1.0)
+ }
+ engine.RootContext().SetContextProperty("gcd", gcd)
+
+ var androidCwtchActivity = android.NewCwtchActivity(nil)
+ engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity)
+ /*if runtime.GOOS == "android" {
+ androidCwtchActivity.StartCwtchService()
+ }*/
+
+ //engine.addImportPath(QStringLiteral("qrc:/"));
+ //engine.load(QUrl(QStringLiteral("qrc:/source/qml/main.qml")));
+
+ engine.Load(qmlSource)
+
+ the.ACN = nil
+ go loadNetworkingAndFiles(gcd)
+
+ app.Exec()
}
- engine.RootContext().SetContextProperty("gcd", gcd)
-
- var androidCwtchActivity = android.NewCwtchActivity(nil)
- engine.RootContext().SetContextProperty("androidCwtchActivity", androidCwtchActivity)
-
- engine.Load(qmlSource)
- the.ACN = nil
- go loadNetworkingAndFiles(gcd)
- app.Exec()
if the.ACN != nil {
the.ACN.Close()
}
+ log.Infoln("Exiting main()")
}
func loadNetworkingAndFiles(gcd *gothings.GrandCentralDispatcher) {