Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit ba2010b

Browse files
Add files via upload
1 parent 701a0cf commit ba2010b

7 files changed

Lines changed: 357 additions & 0 deletions

File tree

16 KB
Binary file not shown.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.beeware.android;
2+
3+
public class DrawHandlerView extends android.view.View {
4+
private IDrawHandler drawHandler = null;
5+
6+
public DrawHandlerView(android.content.Context context) {
7+
super(context);
8+
}
9+
10+
public void setDrawHandler(IDrawHandler drawHandler) {
11+
this.drawHandler = drawHandler;
12+
}
13+
14+
public void onDraw(android.graphics.Canvas canvas) {
15+
super.onDraw(canvas);
16+
drawHandler.handleDraw(canvas);
17+
}
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.beeware.android;
2+
3+
public interface IDrawHandler {
4+
public void handleDraw(android.graphics.Canvas canvas);
5+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.beeware.android;
2+
3+
import android.content.Intent;
4+
import android.content.res.Configuration;
5+
import android.view.Menu;
6+
import android.view.MenuItem;
7+
8+
public interface IPythonApp {
9+
void onCreate();
10+
void onResume();
11+
void onStart();
12+
void onActivityResult(int requestCode, int resultCode, Intent data);
13+
void onConfigurationChanged(Configuration newConfig);
14+
boolean onOptionsItemSelected(MenuItem menuitem);
15+
boolean onPrepareOptionsMenu(Menu menu);
16+
// There's no need to add any more methods to this interface, as the Python
17+
// call mechanism no longer uses it.
18+
}
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
package org.beeware.android;
2+
3+
import android.content.Intent;
4+
import android.content.res.Configuration;
5+
import android.os.Bundle;
6+
import android.util.Log;
7+
import android.view.Menu;
8+
import android.view.MenuItem;
9+
import android.widget.LinearLayout;
10+
11+
import androidx.appcompat.app.AppCompatActivity;
12+
13+
import com.chaquo.python.Kwarg;
14+
import com.chaquo.python.PyException;
15+
import com.chaquo.python.PyObject;
16+
import com.chaquo.python.Python;
17+
import com.chaquo.python.android.AndroidPlatform;
18+
19+
import java.util.List;
20+
21+
import org.json.JSONArray;
22+
import org.json.JSONException;
23+
24+
import com.arshiacomplus.warpscanner.warpscanner.R;
25+
26+
import android.app.Activity;
27+
28+
import android.os.StrictMode;
29+
30+
public class MainActivity extends AppCompatActivity {
31+
32+
33+
34+
// To profile app launch, use `adb -s MainActivity`; look for "onCreate() start" and "onResume() completed".
35+
private String TAG = "MainActivity";
36+
private static PyObject pythonApp;
37+
38+
39+
40+
/**
41+
* This method is called by `app.__main__` over JNI in Python when the BeeWare
42+
* app launches.
43+
*
44+
* @param app
45+
*/
46+
@SuppressWarnings("unused")
47+
public static void setPythonApp(IPythonApp app) {
48+
pythonApp = PyObject.fromJava(app);
49+
}
50+
51+
/**
52+
* We store the MainActivity instance on the *class* so that we can easily
53+
* access it from Python.
54+
*/
55+
public static MainActivity singletonThis;
56+
57+
protected void onCreate(Bundle savedInstanceState) {
58+
Log.d(TAG, "onCreate() start");
59+
// Change away from the splash screen theme to the app theme.
60+
setTheme(R.style.AppTheme);
61+
super.onCreate(savedInstanceState);
62+
LinearLayout layout = new LinearLayout(this);
63+
this.setContentView(layout);
64+
singletonThis = this;
65+
66+
67+
68+
69+
// Call PermissionUtils to request permissions
70+
PermissionUtils.requestStoragePermissions(this);
71+
72+
73+
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
74+
StrictMode.setThreadPolicy(policy);
75+
76+
// فراخوانی بررسی نسخه
77+
VersionChecker.checkVersion(this);
78+
79+
Python py;
80+
if (Python.isStarted()) {
81+
Log.d(TAG, "Python already started");
82+
py = Python.getInstance();
83+
} else {
84+
Log.d(TAG, "Starting Python");
85+
AndroidPlatform platform = new AndroidPlatform(this);
86+
platform.redirectStdioToLogcat();
87+
Python.start(platform);
88+
py = Python.getInstance();
89+
90+
String argvStr = getIntent().getStringExtra("org.beeware.ARGV");
91+
if (argvStr != null) {
92+
try {
93+
JSONArray argvJson = new JSONArray(argvStr);
94+
List<PyObject> sysArgv = py.getModule("sys").get("argv").asList();
95+
for (int i = 0; i < argvJson.length(); i++) {
96+
sysArgv.add(PyObject.fromJava(argvJson.getString(i)));
97+
}
98+
} catch (JSONException e) {
99+
throw new RuntimeException(e);
100+
}
101+
}
102+
}
103+
104+
Log.d(TAG, "Running main module " + getString(R.string.main_module));
105+
py.getModule("runpy").callAttr(
106+
"run_module",
107+
getString(R.string.main_module),
108+
new Kwarg("run_name", "__main__"),
109+
new Kwarg("alter_sys", true)
110+
);
111+
112+
userCode("onCreate");
113+
Log.d(TAG, "onCreate() complete");
114+
}
115+
116+
protected void onStart() {
117+
Log.d(TAG, "onStart() start");
118+
super.onStart();
119+
userCode("onStart");
120+
Log.d(TAG, "onStart() complete");
121+
}
122+
123+
protected void onResume() {
124+
Log.d(TAG, "onResume() start");
125+
super.onResume();
126+
userCode("onResume");
127+
Log.d(TAG, "onResume() complete");
128+
}
129+
130+
protected void onPause() {
131+
Log.d(TAG, "onPause() start");
132+
super.onPause();
133+
userCode("onPause");
134+
Log.d(TAG, "onPause() complete");
135+
}
136+
137+
protected void onStop() {
138+
Log.d(TAG, "onStop() start");
139+
super.onStop();
140+
userCode("onStop");
141+
Log.d(TAG, "onStop() complete");
142+
}
143+
protected void onDestroy() {
144+
Log.d(TAG, "onDestroy() start");
145+
super.onDestroy();
146+
userCode("onDestroy");
147+
Log.d(TAG, "onDestroy() complete");
148+
}
149+
protected void onRestart() {
150+
Log.d(TAG, "onRestart() start");
151+
super.onRestart();
152+
userCode("onRestart");
153+
Log.d(TAG, "onRestart() complete");
154+
}
155+
public void onTopResumedActivityChanged (boolean isTopResumedActivity){
156+
Log.d(TAG, "onTopResumedActivityChanged() start");
157+
super.onTopResumedActivityChanged(isTopResumedActivity);
158+
userCode("onTopResumedActivityChanged", isTopResumedActivity);
159+
Log.d(TAG, "onTopResumedActivityChanged() complete");
160+
}
161+
162+
protected void onActivityResult(int requestCode, int resultCode, Intent data)
163+
{
164+
Log.d(TAG, "onActivityResult() start");
165+
super.onActivityResult(requestCode, resultCode, data);
166+
userCode("onActivityResult", requestCode, resultCode, data);
167+
Log.d(TAG, "onActivityResult() complete");
168+
}
169+
170+
public void onConfigurationChanged(Configuration newConfig) {
171+
Log.d(TAG, "onConfigurationChanged() start");
172+
super.onConfigurationChanged(newConfig);
173+
userCode("onConfigurationChanged", newConfig);
174+
Log.d(TAG, "onConfigurationChanged() complete");
175+
}
176+
177+
public boolean onOptionsItemSelected(MenuItem menuitem) {
178+
Log.d(TAG, "onOptionsItemSelected() start");
179+
PyObject pyResult = userCode("onOptionsItemSelected", menuitem);
180+
boolean result = (pyResult == null) ? false : pyResult.toBoolean();
181+
Log.d(TAG, "onOptionsItemSelected() complete");
182+
return result;
183+
}
184+
185+
public boolean onPrepareOptionsMenu(Menu menu) {
186+
Log.d(TAG, "onPrepareOptionsMenu() start");
187+
PyObject pyResult = userCode("onPrepareOptionsMenu", menu);
188+
boolean result = (pyResult == null) ? false : pyResult.toBoolean();
189+
Log.d(TAG, "onPrepareOptionsMenu() complete");
190+
return result;
191+
}
192+
193+
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
194+
{
195+
Log.d(TAG, "onRequestPermissionsResult() start");
196+
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
197+
userCode("onRequestPermissionsResult", requestCode, permissions, grantResults);
198+
Log.d(TAG, "onRequestPermissionsResult() complete");
199+
}
200+
201+
private PyObject userCode(String methodName, Object... args) {
202+
if (pythonApp == null) {
203+
// Could be a non-graphical app such as Python-support-testbed.
204+
return null;
205+
}
206+
try {
207+
if (pythonApp.containsKey(methodName)) {
208+
return pythonApp.callAttr(methodName, args);
209+
} else {
210+
// Handle the case where the method doesn't exist
211+
return null;
212+
}
213+
} catch (PyException e) {
214+
if (e.getMessage().startsWith("NotImplementedError")) {
215+
return null;
216+
}
217+
throw e;
218+
}
219+
}
220+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.beeware.android;
2+
3+
import android.Manifest;
4+
import android.app.Activity;
5+
import android.content.pm.PackageManager;
6+
import androidx.core.app.ActivityCompat;
7+
import androidx.core.content.ContextCompat;
8+
9+
public class PermissionUtils {
10+
public static void requestStoragePermissions(Activity activity) {
11+
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
12+
ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
13+
14+
ActivityCompat.requestPermissions(activity, new String[]{
15+
Manifest.permission.READ_EXTERNAL_STORAGE,
16+
Manifest.permission.WRITE_EXTERNAL_STORAGE
17+
}, 1);
18+
}
19+
}
20+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.beeware.android;
2+
3+
import android.app.Activity;
4+
import android.app.AlertDialog;
5+
import android.content.DialogInterface;
6+
import android.content.Intent;
7+
import android.net.Uri;
8+
import android.os.Handler;
9+
import android.os.Looper;
10+
11+
import java.io.BufferedReader;
12+
import java.io.InputStreamReader;
13+
import java.net.HttpURLConnection;
14+
import java.net.URL;
15+
16+
public class VersionChecker {
17+
18+
public static void checkVersion(Activity activity) {
19+
new Thread(new Runnable() {
20+
@Override
21+
public void run() {
22+
String link = "https://raw.githubusercontent.com/arshiacomplus/WarpScanner-android-GUI/refs/heads/main/android-toga/version.txt";
23+
String content = getContentFromURL(link);
24+
25+
if (!"v0.0.4".equals(content.trim())) {
26+
// نمایش دیالوگ در نخ اصلی
27+
new Handler(Looper.getMainLooper()).post(new Runnable() {
28+
@Override
29+
public void run() {
30+
showUpdateDialog(activity);
31+
}
32+
});
33+
}
34+
}
35+
}).start();
36+
}
37+
38+
private static String getContentFromURL(String link) {
39+
StringBuilder content = new StringBuilder();
40+
try {
41+
URL url = new URL(link);
42+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
43+
connection.setRequestMethod("GET");
44+
45+
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
46+
String inputLine;
47+
48+
while ((inputLine = in.readLine()) != null) {
49+
content.append(inputLine);
50+
}
51+
in.close();
52+
} catch (Exception e) {
53+
e.printStackTrace();
54+
}
55+
return content.toString();
56+
}
57+
58+
private static void showUpdateDialog(Activity activity) {
59+
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
60+
builder.setMessage("بروزرسانی در دسترس است")
61+
.setCancelable(false)
62+
.setPositiveButton("برو", new DialogInterface.OnClickListener() {
63+
public void onClick(DialogInterface dialog, int id) {
64+
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/arshiacomplus/WarpScanner-android-GUI/"));
65+
activity.startActivity(browserIntent);
66+
}
67+
})
68+
.setNegativeButton("بستن", new DialogInterface.OnClickListener() {
69+
public void onClick(DialogInterface dialog, int id) {
70+
dialog.dismiss();
71+
}
72+
});
73+
AlertDialog alert = builder.create();
74+
alert.show();
75+
}
76+
}

0 commit comments

Comments
 (0)