Skip to content

Commit c9d4c81

Browse files
Add files via upload
1 parent 437b622 commit c9d4c81

17 files changed

Lines changed: 767 additions & 0 deletions

File tree

AndroidManifest.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
package="com.symphonyrecords.debugger"
5+
android:installLocation="auto">
6+
7+
8+
<!--Just for Debugging ( remove this on release)-->
9+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
10+
<uses-permission android:name="android.permission.READ_LOGS" tools:ignore="ProtectedPermissions" />
11+
12+
13+
<application
14+
android:icon="@mipmap/ic_launcher"
15+
android:label="Android Debugger">
16+
17+
<activity android:name=".MainActivity" />
18+
19+
<!--Just for Debugging ( remove this on release)-->
20+
<service android:name=".DebuggerService" />
21+
22+
</application>
23+
24+
</manifest>
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
package com.symphonyrecords.debugger;
2+
3+
4+
import android.annotation.SuppressLint;
5+
import android.app.Notification;
6+
import android.app.Service;
7+
import android.content.Context;
8+
import android.content.Intent;
9+
import android.graphics.PixelFormat;
10+
import android.os.Build;
11+
import android.os.IBinder;
12+
import android.text.SpannableString;
13+
import android.text.Spanned;
14+
import android.text.TextUtils;
15+
import android.text.style.ForegroundColorSpan;
16+
import android.util.DisplayMetrics;
17+
import android.view.Gravity;
18+
import android.view.LayoutInflater;
19+
import android.view.MotionEvent;
20+
import android.view.View;
21+
import android.view.ViewGroup;
22+
import android.view.WindowManager;
23+
import android.widget.RelativeLayout;
24+
import android.widget.ScrollView;
25+
import android.widget.TextView;
26+
27+
import androidx.appcompat.widget.AppCompatImageView;
28+
import androidx.core.content.ContextCompat;
29+
import androidx.core.widget.NestedScrollView;
30+
31+
import com.symphonyrecords.debugger.R;
32+
33+
import java.lang.ref.WeakReference;
34+
35+
@SuppressLint({"RtlHardcoded", "ClickableViewAccessibility", "InflateParams"})
36+
public class DebuggerService extends Service {
37+
38+
private boolean isMinimized = true;
39+
private boolean isShowing = true;
40+
41+
private WindowManager mWindowManager;
42+
RelativeLayout root_view;
43+
private View mView;
44+
private TextView textView;
45+
private NestedScrollView scrollView;
46+
private AppCompatImageView btnResize;
47+
private AppCompatImageView btnClose;
48+
private AppCompatImageView btnReset;
49+
private CharSequence msg = "";
50+
private Spanned spanColor;
51+
52+
53+
int paramWidth;
54+
int paramHeight;
55+
float scale;
56+
57+
private static WeakReference<DebuggerService> mWeakReferenceContext;
58+
59+
public static void init(DebuggerService ctx) {
60+
mWeakReferenceContext = new WeakReference<>(ctx);
61+
}
62+
63+
/**
64+
* get WeakReference instance of {@link DebuggerService} class
65+
*/
66+
public static DebuggerService getContext() {
67+
try {
68+
if (null != mWeakReferenceContext && null != mWeakReferenceContext.get()) {
69+
return mWeakReferenceContext.get();
70+
}
71+
} catch (Throwable e) {
72+
e.printStackTrace();
73+
}
74+
return null;
75+
}
76+
77+
78+
@Override
79+
public IBinder onBind(Intent intent) {
80+
return null;
81+
}
82+
83+
@Override
84+
public void onCreate() {
85+
super.onCreate();
86+
87+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
88+
startForeground(1, new Notification());
89+
}
90+
91+
init(this);
92+
93+
DisplayMetrics metrics = getResources().getDisplayMetrics();
94+
paramWidth = (int) (metrics.widthPixels * 0.7f);
95+
paramHeight = (int) (metrics.heightPixels * 0.45f);
96+
97+
scale = metrics.density;
98+
99+
}
100+
101+
@Override
102+
public int onStartCommand(Intent intent, int flags, int startId) {
103+
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
104+
initUI();
105+
moveView();
106+
return super.onStartCommand(intent, flags, startId);
107+
}
108+
109+
@Override
110+
public void onDestroy() {
111+
try {
112+
if (null != mView && null != mWindowManager) {
113+
mWindowManager.removeView(mView);
114+
mWindowManager = null;
115+
}
116+
} catch (Throwable e) {
117+
e.printStackTrace();
118+
}
119+
120+
121+
super.onDestroy();
122+
}
123+
124+
WindowManager.LayoutParams mWindowsParams;
125+
126+
private void moveView() {
127+
128+
129+
initializeLayoutParams(paramWidth, paramHeight);
130+
131+
132+
mWindowsParams.gravity = Gravity.TOP | Gravity.LEFT;
133+
mWindowsParams.y = 100;
134+
mWindowManager.addView(mView, mWindowsParams);
135+
136+
137+
mView.setOnTouchListener(new View.OnTouchListener() {
138+
139+
private int initialX;
140+
private int initialY;
141+
private float initialTouchX;
142+
private float initialTouchY;
143+
144+
long startTime = System.currentTimeMillis();
145+
146+
147+
@Override
148+
public boolean onTouch(View v, MotionEvent event) {
149+
150+
151+
if (System.currentTimeMillis() - startTime <= 300) {
152+
return false;
153+
}
154+
155+
156+
// switch (event.getAction()) {
157+
switch (event.getActionMasked()) {
158+
159+
case MotionEvent.ACTION_DOWN:
160+
initialX = mWindowsParams.x;
161+
initialY = mWindowsParams.y;
162+
initialTouchX = event.getRawX();
163+
initialTouchY = event.getRawY();
164+
break;
165+
166+
case MotionEvent.ACTION_UP:
167+
break;
168+
169+
case MotionEvent.ACTION_MOVE:
170+
mWindowsParams.x = initialX + (int) (event.getRawX() - initialTouchX);
171+
mWindowsParams.y = initialY + (int) (event.getRawY() - initialTouchY);
172+
mWindowManager.updateViewLayout(mView, mWindowsParams);
173+
break;
174+
}
175+
// mView.invalidate();
176+
return false;
177+
}
178+
});
179+
180+
// mView.findViewById(R.id.dragPanel).bringToFront();
181+
mView.findViewById(R.id.touch_disable_container).setOnClickListener(view -> {
182+
// This is only for preventing to log screen move. only debugger header should be dragged
183+
});
184+
185+
186+
btnResize.setOnClickListener(view -> {
187+
if (isMinimized) {
188+
initializeLayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
189+
btnResize.setImageResource(R.drawable.ic_maximize);
190+
isMinimized = false;
191+
} else {
192+
initializeLayoutParams(paramWidth, paramHeight);
193+
btnResize.setImageResource(R.drawable.ic_minimize);
194+
isMinimized = true;
195+
}
196+
mWindowManager.updateViewLayout(mView, mWindowsParams);
197+
});
198+
199+
200+
mView.findViewById(R.id.btnDrop).setOnClickListener(view -> {
201+
if (isShowing) {
202+
// scrollView.setLayoutParams(new RelativeLayout.LayoutParams(dropSize, dropSize));
203+
btnClose.setVisibility(View.GONE);
204+
btnResize.setVisibility(View.GONE);
205+
btnReset.setVisibility(View.GONE);
206+
root_view.getLayoutParams().width = (int) (55 * scale + 0.5f);
207+
root_view.getLayoutParams().height = (int) (40 * scale + 0.5f);
208+
isShowing = false;
209+
210+
} else {
211+
btnClose.setVisibility(View.VISIBLE);
212+
btnResize.setVisibility(View.VISIBLE);
213+
btnReset.setVisibility(View.VISIBLE);
214+
root_view.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
215+
root_view.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
216+
btnResize.setImageResource(R.drawable.ic_minimize);
217+
isMinimized = true;
218+
initializeLayoutParams(paramWidth, paramHeight);
219+
isShowing = true;
220+
}
221+
mWindowManager.updateViewLayout(mView, mWindowsParams);
222+
});
223+
224+
225+
}
226+
227+
private void initializeLayoutParams(int width, int height) {
228+
// if you got any problems with FLAG_NOT_FOCUSABLE replace it with FLAG_WATCH_OUTSIDE_TOUCH
229+
// FLAG_WATCH_OUTSIDE_TOUCH will cause keyboard will not pop up and back press will not work
230+
// this is why I replace it with FLAG_NOT_FOCUSABLE
231+
mWindowsParams =
232+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
233+
?
234+
new WindowManager.LayoutParams(width, height, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT)
235+
:
236+
new WindowManager.LayoutParams(width, height, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
237+
}
238+
239+
240+
private void initUI() {
241+
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
242+
if (layoutInflater != null) {
243+
mView = layoutInflater.inflate(R.layout.debugger_layout, null);
244+
root_view = mView.findViewById(R.id.root_debugger);
245+
scrollView = mView.findViewById(R.id.scroll_view);
246+
btnResize = mView.findViewById(R.id.btnResize);
247+
btnClose = mView.findViewById(R.id.btnClose);
248+
btnReset = mView.findViewById(R.id.btnReset);
249+
btnClose.setOnClickListener(view -> stopSelf());
250+
btnReset.setOnClickListener(view -> {
251+
if (null != textView) {
252+
textView.setText(null);
253+
}
254+
msg = "";
255+
spanColor = null;
256+
textView = null;
257+
});
258+
}
259+
}
260+
261+
262+
/**
263+
* Don't Change the order of this method code lines.
264+
*/
265+
private void addTextViewToLayout(String text, int textColor) {
266+
spanColor = setSpanColor(text, ContextCompat.getColor(this, textColor));
267+
msg = TextUtils.concat(msg, "\n\n", spanColor);
268+
if (null == textView) {
269+
textView = mView.findViewById(R.id.message_output);
270+
textView.setGravity(Gravity.LEFT);
271+
}
272+
textView.setText(msg);
273+
274+
if (!scrollView.canScrollVertically(1)) {
275+
scrollView.post(() -> {
276+
scrollView.smoothScrollTo(0, scrollView.getHeight());
277+
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
278+
});
279+
}
280+
mWindowManager.updateViewLayout(mView, mWindowsParams);
281+
}
282+
283+
private Spanned setSpanColor(String s, int color) {
284+
SpannableString ss = new SpannableString(s);
285+
ss.setSpan(new ForegroundColorSpan(color), 0, s.length(), 0);
286+
return ss;
287+
}
288+
289+
public static void setDebugText(String msg, int textColor) {
290+
if (null != getContext()) getContext().addTextViewToLayout(msg, textColor);
291+
}
292+
293+
294+
public static void stop() {
295+
if (null != getContext()) getContext().stopSelf();
296+
}
297+
298+
299+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.symphonyrecords.debugger;
2+
3+
import android.app.Activity;
4+
import android.content.Intent;
5+
import android.net.Uri;
6+
import android.os.Build;
7+
import android.os.Bundle;
8+
import android.provider.Settings;
9+
import android.widget.Toast;
10+
11+
import androidx.core.content.ContextCompat;
12+
13+
import com.symphonyrecords.debugger.DebuggerService;
14+
15+
16+
public class MainActivity extends Activity {
17+
18+
public final static int Overlay_REQUEST_CODE = 251;
19+
20+
@Override
21+
protected void onCreate(Bundle savedInstanceState) {
22+
super.onCreate(savedInstanceState);
23+
24+
checkDrawOverlayPermission(this);
25+
}
26+
27+
28+
public void checkDrawOverlayPermission(Activity activity) {
29+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
30+
if (!Settings.canDrawOverlays(this)) {
31+
if (null != activity) {
32+
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
33+
activity.startActivityForResult(intent, Overlay_REQUEST_CODE);
34+
} else {
35+
Toast.makeText(this, "Please grant \"Draw over other apps\" permission under application settings", Toast.LENGTH_LONG).show();
36+
}
37+
} else {
38+
openFloatingWindow();
39+
}
40+
} else {
41+
openFloatingWindow();
42+
}
43+
}
44+
45+
private void openFloatingWindow() {
46+
Intent intent = new Intent(this, DebuggerService.class);
47+
this.stopService(intent);
48+
ContextCompat.startForegroundService(this, intent);
49+
}
50+
51+
52+
@Override
53+
public void onActivityResult(int requestCode, int resultCode, Intent data) {
54+
super.onActivityResult(requestCode, resultCode, data);
55+
if (resultCode == RESULT_OK) {
56+
if (requestCode == Overlay_REQUEST_CODE) {
57+
if (Build.VERSION.SDK_INT >= 23) {
58+
if (Settings.canDrawOverlays(this)) {
59+
openFloatingWindow();
60+
}
61+
} else {
62+
openFloatingWindow();
63+
}
64+
}
65+
}
66+
}
67+
68+
69+
}

0 commit comments

Comments
 (0)