From cc15b326a4cf793331cd49d35ef1339346bb32e0 Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 22:55:37 -0400 Subject: [PATCH 01/17] Add missing super calls in overridden methods. --- BTLib/src/com/offsetnull/bt/launcher/Launcher.java | 1 + .../com/offsetnull/bt/settings/ColorSwatchPreference.java | 3 ++- BTLib/src/com/offsetnull/bt/window/MainWindow.java | 7 +++++-- BTLib/src/com/offsetnull/bt/window/Window.java | 3 +++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/BTLib/src/com/offsetnull/bt/launcher/Launcher.java b/BTLib/src/com/offsetnull/bt/launcher/Launcher.java index 9628da58..dd9611ea 100644 --- a/BTLib/src/com/offsetnull/bt/launcher/Launcher.java +++ b/BTLib/src/com/offsetnull/bt/launcher/Launcher.java @@ -2012,6 +2012,7 @@ public void onClick(View view) { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); boolean external = false; if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { external = true; diff --git a/BTLib/src/com/offsetnull/bt/settings/ColorSwatchPreference.java b/BTLib/src/com/offsetnull/bt/settings/ColorSwatchPreference.java index 360a5e74..e18ed0c8 100644 --- a/BTLib/src/com/offsetnull/bt/settings/ColorSwatchPreference.java +++ b/BTLib/src/com/offsetnull/bt/settings/ColorSwatchPreference.java @@ -50,7 +50,8 @@ public View onCreateView(ViewGroup root) { } public void onBindView(View v) { - + super.onBindView(v); + Button b = (Button) v.findViewById(R.id.colorswatch); TextView summary = (TextView) v.findViewById(android.R.id.summary); summary.setText("Text for your viewing pleasuer."); diff --git a/BTLib/src/com/offsetnull/bt/window/MainWindow.java b/BTLib/src/com/offsetnull/bt/window/MainWindow.java index 74acb301..2d7c4e45 100644 --- a/BTLib/src/com/offsetnull/bt/window/MainWindow.java +++ b/BTLib/src/com/offsetnull/bt/window/MainWindow.java @@ -1993,7 +1993,7 @@ public void onClick(DialogInterface dialog, int id) { builder.show(); //alert.show(); - //super.onBackPressed(); + super.onBackPressed(); } int OREINTATION = Configuration.ORIENTATION_LANDSCAPE; @@ -2201,7 +2201,8 @@ public void onRestoreInstanceState(Bundle data) { } public void onActivityResult(int requestCode, int resultCode, Intent data) { - + super.onActivityResult(requestCode, resultCode, data); + if(resultCode == RESULT_OK) { //Log.e("WINDOW","onActivityResult()"); settingsDialogRun = true; @@ -3147,6 +3148,7 @@ public double getTitleBarHeight() { @Override public void onNewIntent(Intent i) { + super.onNewIntent(i); //this is if the activity is currently open, and a new intent has been posted. Log.e("new intent","new intent : " + i.getStringExtra("DISPLAY")); @@ -3263,6 +3265,7 @@ public void onClick(View view) { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); boolean external = false; if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { external = true; diff --git a/BTLib/src/com/offsetnull/bt/window/Window.java b/BTLib/src/com/offsetnull/bt/window/Window.java index f0e83062..e56718e2 100644 --- a/BTLib/src/com/offsetnull/bt/window/Window.java +++ b/BTLib/src/com/offsetnull/bt/window/Window.java @@ -344,11 +344,13 @@ public final void displayLuaError(final String message) { @Override protected final void onAttachedToWindow() { + super.onAttachedToWindow(); windowShowing = true; } @Override protected final void onDetachedFromWindow() { + super.onDetachedFromWindow(); windowShowing = false; } @@ -3120,6 +3122,7 @@ public void onCustomAnimationEnd() { @Override public void onAnimationEnd() { + super.onAnimationEnd(); //call into lua to notify that the parent animation has completed. callFunction("onAnimationEnd",null); } From af8145c19b21d12e1bdb9ec95385ede9414bd294 Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 23:09:47 -0400 Subject: [PATCH 02/17] Move allocations out of onDraw methods into preallocated fields. --- .../bt/button/ColorPickerDialog.java | 26 ++- .../com/offsetnull/bt/button/SlickButton.java | 94 +++++---- .../offsetnull/bt/timer/ProgressMeter.java | 50 ++--- .../src/com/offsetnull/bt/window/Window.java | 186 ++++++++++-------- 4 files changed, 196 insertions(+), 160 deletions(-) diff --git a/BTLib/src/com/offsetnull/bt/button/ColorPickerDialog.java b/BTLib/src/com/offsetnull/bt/button/ColorPickerDialog.java index 1fe587b2..013e5f5a 100644 --- a/BTLib/src/com/offsetnull/bt/button/ColorPickerDialog.java +++ b/BTLib/src/com/offsetnull/bt/button/ColorPickerDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.button; +import android.annotation.SuppressLint; import android.os.Bundle; import android.app.Dialog; import android.content.Context; @@ -33,6 +34,9 @@ private static class ColorPickerView extends View implements SeekBar.OnSeekBarCh //private ButtonEditorDialog.COLOR_FIELDS thefield; private Path circle_path; private Paint mCenterCircle; + private final RectF mOvalRect = new RectF(); + private final Matrix mRotationMatrix = new Matrix(); + private final RectF mDrawOvalRect = new RectF(); ColorPickerView(Context c, OnColorChangedListener l, int color) { super(c); @@ -95,21 +99,26 @@ protected void onDraw(Canvas canvas) { //CENTER_RADIUS = (int) (21*scale); //float r = CENTER_RADIUS; - circle_path = new Path(); + if (circle_path == null) { + circle_path = new Path(); + } else { + circle_path.reset(); + } //circle_path.addCircle(0, 0, (float) (r*0.5), Direction.CW); float nr = (float) (mCenterPaint.getStrokeWidth() + CENTER_RADIUS + 5 * this.getContext().getResources().getDisplayMetrics().density); - circle_path.addOval(new RectF(-nr, -nr, nr, nr), Direction.CW); - Matrix m = new Matrix(); - m.reset(); - m.postRotate(-190); - circle_path.transform(m); + mOvalRect.set(-nr, -nr, nr, nr); + circle_path.addOval(mOvalRect, Direction.CW); + mRotationMatrix.reset(); + mRotationMatrix.postRotate(-190); + circle_path.transform(mRotationMatrix); canvas.translate(CENTER_X, CENTER_X); canvas.drawTextOnPath("Select Inside To Confirm.", circle_path, 0, -3, mCenterIndicator); canvas.drawPath(circle_path, mCenterCircle); - - canvas.drawOval(new RectF(-r, -r, r, r), mPaint); + + mDrawOvalRect.set(-r, -r, r, r); + canvas.drawOval(mDrawOvalRect, mPaint); canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint); if (mTrackingCenter) { @@ -289,6 +298,7 @@ public ColorPickerDialog(Context context, + @SuppressLint("ResourceType") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/BTLib/src/com/offsetnull/bt/button/SlickButton.java b/BTLib/src/com/offsetnull/bt/button/SlickButton.java index 152c052a..1eb668c4 100644 --- a/BTLib/src/com/offsetnull/bt/button/SlickButton.java +++ b/BTLib/src/com/offsetnull/bt/button/SlickButton.java @@ -2,6 +2,7 @@ //import java.io.UnsupportedEncodingException; //import java.nio.ByteBuffer; +import java.lang.ref.WeakReference; import com.offsetnull.bt.window.MainWindow; @@ -81,35 +82,7 @@ public SlickButton(Context context,int px,int py) { data.setLabel("NULL!"); updateRect(); - myhandler = new Handler(Looper.getMainLooper()) { - public void handleMessage(Message msg) { - switch(msg.what) { - case MSG_BEGINMOVE: - moving = true; - SlickButton.this.invalidate(); - - //SlickButton.this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - dispatcher.sendEmptyMessage(856); //the haptic feeback message - //SlickButton.this.invalidate(SlickButton.this.rect); //only invaldate my rect. - break; - case MSG_DELETE: - //SlickButton.this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - dispatcher.sendEmptyMessage(856); //the haptic feeback message - - dialog_launched = true; - button_down = false; - moving = false; - nudged = false; - hasfocus = false; - if(!lockEdit) { - //Message deleme = deleter.obtainMessage(ByteView.MSG_DELETEBUTTON, SlickButton.this); - //deleter.sendMessage(deleme); - } - //dispatcher. - break; - } - } - }; + myhandler = new SlickButtonHandler(this); //Log.e("SB","SLICKBUTTON CONSTRUCTOR PASSED"); @@ -445,6 +418,10 @@ public boolean onTouchEvent(MotionEvent e) { }*/ Paint p = new Paint(); Paint opts = new Paint(); + private final RectF mDrawRectF = new RectF(); + private final Rect mMovingRect = new Rect(); + private final Paint mMovingPaint = new Paint(); + private final RectF mMovingRectF = new RectF(); public void onDraw(Canvas c) { //c. //Log.e("BUTTON","DRAWING BUTTON!"); @@ -489,9 +466,9 @@ public void onDraw(Canvas c) { if(drawRound) { p.setAntiAlias(true); - - RectF frect = new RectF(rect); - c.drawRoundRect(frect, radius,radius, p); + + mDrawRectF.set(rect); + c.drawRoundRect(mDrawRectF, radius,radius, p); } else { p.setAntiAlias(false); @@ -524,18 +501,16 @@ public void onDraw(Canvas c) { //c.drawText(data.getLabel(), data.getX()-tsize/2, data.getY()+12, opts); if(moving) { - Rect m_rect = new Rect(); - m_rect.set(data.getX()-(int)((data.getWidth()*density)/2)+5,data.getY()-(int)((data.getHeight()*density)/2)+5,data.getX()+(int)((data.getWidth()*density)/2)-5,data.getY()+(int)((data.getHeight()*density)/2)-5); - Paint rpaint = new Paint(); - rpaint.setColor(0xAAFF0000); - - + mMovingRect.set(data.getX()-(int)((data.getWidth()*density)/2)+5,data.getY()-(int)((data.getHeight()*density)/2)+5,data.getX()+(int)((data.getWidth()*density)/2)-5,data.getY()+(int)((data.getHeight()*density)/2)-5); + mMovingPaint.setColor(0xAAFF0000); + + if(drawRound) { float rradius = 5 * this.getResources().getDisplayMetrics().density; - RectF frect = new RectF(m_rect); - c.drawRoundRect(frect, radius,rradius, rpaint); + mMovingRectF.set(mMovingRect); + c.drawRoundRect(mMovingRectF, radius,rradius, mMovingPaint); } else { - c.drawRect(m_rect, rpaint); + c.drawRect(mMovingRect, mMovingPaint); } //RectF frect = new RectF(m_rect); @@ -668,7 +643,40 @@ public void setLockMove(boolean lockMove) { public boolean isLockMove() { return lockMove; } - - + private static class SlickButtonHandler extends Handler { + private final WeakReference ref; + SlickButtonHandler(SlickButton outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(Message msg) { + SlickButton outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case MSG_BEGINMOVE: + outer.moving = true; + outer.invalidate(); + //SlickButton.this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + outer.dispatcher.sendEmptyMessage(856); //the haptic feeback message + //SlickButton.this.invalidate(SlickButton.this.rect); //only invaldate my rect. + break; + case MSG_DELETE: + //SlickButton.this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + outer.dispatcher.sendEmptyMessage(856); //the haptic feeback message + outer.dialog_launched = true; + outer.button_down = false; + outer.moving = false; + outer.nudged = false; + outer.hasfocus = false; + if(!outer.lockEdit) { + //Message deleme = deleter.obtainMessage(ByteView.MSG_DELETEBUTTON, SlickButton.this); + //deleter.sendMessage(deleme); + } + //dispatcher. + break; + } + } + } } diff --git a/BTLib/src/com/offsetnull/bt/timer/ProgressMeter.java b/BTLib/src/com/offsetnull/bt/timer/ProgressMeter.java index 0bd32dd6..88ddb5ca 100644 --- a/BTLib/src/com/offsetnull/bt/timer/ProgressMeter.java +++ b/BTLib/src/com/offsetnull/bt/timer/ProgressMeter.java @@ -13,24 +13,37 @@ public class ProgressMeter extends View { private float progress; private float range; - + private final Paint mDrawPaint = new Paint(); + private final Rect mDrawRect = new Rect(); + private final Paint mBackgroundPaint = new Paint(); + private static final int[] GRADIENT_COLORS = { 0xFFFF0000, 0xFFEDBF24, 0xFF00FF00 }; + private static final float[] GRADIENT_POSITIONS = { 0f, 0.3f, 1f }; + private Shader mGradientShader; + public ProgressMeter(Context context) { super(context); - + init(); } public ProgressMeter(Context context,AttributeSet set) { super(context,set); init(); } - + private void init() { progress = 25; range = 100; + mBackgroundPaint.setColor(0xFF030303); } //private int indicatorWidth = 10; - + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mGradientShader = new LinearGradient(0, 0, getRight(), 0, GRADIENT_COLORS, GRADIENT_POSITIONS, Shader.TileMode.REPEAT); + } + public void onDraw(Canvas c) { //Log.e("PROGRESS","DRAWING THE PROGRESS BAR"); @@ -39,27 +52,16 @@ public void onDraw(Canvas c) { int indicator_pos = (int) (this.getWidth()*(progress/range)); //c.translate(center_x, center_y); //this.getP - Paint p = new Paint(); - int yellow = 0xFFEDBF24; - //int orange = 0xFFED6124; - int[] colors = { 0xFFFF0000, yellow, 0xFF00FF00 }; - float[] pos = { 0f , 0.3f , 1f }; - Shader s = new LinearGradient(0,0,this.getRight(),0,colors,pos,Shader.TileMode.REPEAT); - - p.setStrokeWidth(19*getResources().getDisplayMetrics().density); - - p.setShader(s); + mDrawPaint.setStrokeWidth(19*getResources().getDisplayMetrics().density); + mDrawPaint.setShader(mGradientShader); //p. - Rect r = new Rect(); - r.top = this.getTop(); - r.bottom = this.getBottom(); - r.left = this.getLeft(); - r.right = this.getRight(); - - Paint alt = new Paint(); - alt.setColor(0xFF030303); - c.drawRect(r, alt); - c.drawLine(0, 0, indicator_pos, 0, p); + mDrawRect.top = this.getTop(); + mDrawRect.bottom = this.getBottom(); + mDrawRect.left = this.getLeft(); + mDrawRect.right = this.getRight(); + + c.drawRect(mDrawRect, mBackgroundPaint); + c.drawLine(0, 0, indicator_pos, 0, mDrawPaint); } diff --git a/BTLib/src/com/offsetnull/bt/window/Window.java b/BTLib/src/com/offsetnull/bt/window/Window.java index e56718e2..bd3d323c 100644 --- a/BTLib/src/com/offsetnull/bt/window/Window.java +++ b/BTLib/src/com/offsetnull/bt/window/Window.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.UnsupportedEncodingException; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.ConcurrentModificationException; @@ -26,6 +27,7 @@ import com.offsetnull.bt.service.plugin.settings.SettingsGroup; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; @@ -41,6 +43,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.Process; import android.content.ClipData; @@ -292,6 +295,7 @@ public class Window extends View implements AnimatedRelativeLayout.OnAnimationEn private String mName = null; /** The clipping rectangle for the draw routine. */ private Rect mClipRect = new Rect(); + private final Rect mTempLinkRect = new Rect(); /** The current link click that is being clicked. */ private StringBuffer mCurrentLink = new StringBuffer(); @@ -401,71 +405,7 @@ private void init(final String dataDir, final String name, final String owner, f mBuffer.debugLineAdd = true; } mHoldBuffer = new TextTree(); - mHandler = new Handler() { - public void handleMessage(final Message msg) { - switch(msg.what) { - case MESSAGE_RESETWITHDATA: - Window.this.resetAndAddText((byte[]) msg.obj); - break; - case MESSAGE_SCROLLLEFT: - mScrollRepeatRate -= (mScrollRepeatRateStep++) * 5; if (mScrollRepeatRate < mScrollRepeatRateMin) { mScrollRepeatRate = mScrollRepeatRateMin; } - Window.this.doScrollLeft(true); - break; - case MESSAGE_SCROLLRIGHT: - mScrollRepeatRate -= (mScrollRepeatRateStep++) *5 ; if (mScrollRepeatRate < mScrollRepeatRateMin) { mScrollRepeatRate = mScrollRepeatRateMin; } - Window.this.doScrollRight(true); - break; - case MESSAGE_SCROLLDOWN: - mScrollRepeatRate -= (mScrollRepeatRateStep++) * 5; if (mScrollRepeatRate < mScrollRepeatRateMin) { mScrollRepeatRate = mScrollRepeatRateMin; } - Window.this.doScrollDown(true); - break; - case MESSAGE_SCROLLUP: - mScrollRepeatRate -= (mScrollRepeatRateStep++) * 5; if (mScrollRepeatRate < mScrollRepeatRateMin) { mScrollRepeatRate = mScrollRepeatRateMin; } - Window.this.doScrollUp(true); - break; - case MESSAGE_STARTSELECTION: - Window.this.startSelection(msg.arg1, msg.arg2); - break; - case MESSAGE_ENCODINGCHANGED: - Window.this.updateEncoding((String) msg.obj); - break; - case MESSAGE_SETTINGSCHANGED: - Window.this.doUpdateSetting(msg.getData().getString("KEY"), msg.getData().getString("VALUE")); - break; - case MESSAGE_CLEARTEXT: - mBuffer.empty(); - mHoldBuffer.empty(); - break; - case MESSAGE_SHUTDOWN: - Window.this.shutdown(); - break; - case MESSAGE_FLUSHBUFFER: - Window.this.flushBuffer(); - break; - case MESSAGE_DRAW: - Window.this.invalidate(); - break; - - case MESSAGE_ADDTEXT: - Window.this.addBytes((byte[]) msg.obj, false); - break; - case MESSAGE_PROCESSXCALLS: - Window.this.xcallS(msg.getData().getString("FUNCTION"), (String) msg.obj); - - break; - case MESSAGE_XCALLB: - //try { - try { - Window.this.xcallB(msg.getData().getString("FUNCTION"), (byte[]) msg.obj); - } catch (LuaException e) { - e.printStackTrace(); - } - break; - default: - break; - } - } - }; + mHandler = new WindowHandler(this); //lua startup. @@ -918,6 +858,7 @@ public void runScriptOnCreate() { } + @SuppressLint("DrawAllocation") @Override public final void onDraw(final Canvas c) { if (selectedSelector != null) { @@ -1240,27 +1181,25 @@ public final void onDraw(final Canvas c) { mCurrentLink.append(text.getString()); - Rect r = new Rect(); - r.left = (int) x; - r.top = (int) (y - p.getTextSize()); - r.right = (int) (x + p.measureText(text.getString())); - r.bottom = (int) (y + 5); + mTempLinkRect.left = (int) x; + mTempLinkRect.top = (int) (y - p.getTextSize()); + mTempLinkRect.right = (int) (x + p.measureText(text.getString())); + mTempLinkRect.bottom = (int) (y + 5); if (mLinkMode == LINK_MODE.BACKGROUND) { linkColor.setColor(mLinkHighlightColor); - c.drawRect(r.left, r.top, r.right, r.bottom, linkColor); + c.drawRect(mTempLinkRect.left, mTempLinkRect.top, mTempLinkRect.right, mTempLinkRect.bottom, linkColor); } - - int linkBoxHeightDips = (int) ((r.bottom - r.top) / this.getResources().getDisplayMetrics().density); + + int linkBoxHeightDips = (int) ((mTempLinkRect.bottom - mTempLinkRect.top) / this.getResources().getDisplayMetrics().density); if (linkBoxHeightDips < mLinkBoxHeightMinimum) { int additionalAmount = (mLinkBoxHeightMinimum - linkBoxHeightDips) / 2; if (additionalAmount > 0) { - r.top -= additionalAmount * this.getResources().getDisplayMetrics().density; - r.bottom += additionalAmount * this.getResources().getDisplayMetrics().density; + mTempLinkRect.top -= additionalAmount * this.getResources().getDisplayMetrics().density; + mTempLinkRect.bottom += additionalAmount * this.getResources().getDisplayMetrics().density; } } - - LinkBox linkbox = new LinkBox(null, r); - linkBoxes.add(linkbox); + + linkBoxes.add(new LinkBox(null, mTempLinkRect)); } } @@ -1513,7 +1452,7 @@ private class LinkBox { */ public LinkBox(final String link, final Rect rect) { //this.mData = link; - this.mBox = rect; + this.mBox = new Rect(rect); } /** Setter for data. * @@ -2848,15 +2787,21 @@ public int execute() throws LuaException { - private Handler callbackHandler = new Handler() { + private static class CallbackHandler extends Handler { + private final WeakReference ref; + CallbackHandler(Window outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { - // + Window outer = ref.get(); + if (outer == null) return; //just call the string. - Window.this.callScheduleCallback(msg.arg1,(String)msg.obj); - - + outer.callScheduleCallback(msg.arg1,(String)msg.obj); } - }; + } + private Handler callbackHandler = new CallbackHandler(this); @@ -4222,5 +4167,76 @@ public TextTree getBuffer() { public double measure(String str) { return featurePaint.measureText(str); } + + private static class WindowHandler extends Handler { + private final WeakReference ref; + WindowHandler(Window outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(final Message msg) { + Window outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case MESSAGE_RESETWITHDATA: + outer.resetAndAddText((byte[]) msg.obj); + break; + case MESSAGE_SCROLLLEFT: + outer.mScrollRepeatRate -= (outer.mScrollRepeatRateStep++) * 5; if (outer.mScrollRepeatRate < outer.mScrollRepeatRateMin) { outer.mScrollRepeatRate = outer.mScrollRepeatRateMin; } + outer.doScrollLeft(true); + break; + case MESSAGE_SCROLLRIGHT: + outer.mScrollRepeatRate -= (outer.mScrollRepeatRateStep++) *5 ; if (outer.mScrollRepeatRate < outer.mScrollRepeatRateMin) { outer.mScrollRepeatRate = outer.mScrollRepeatRateMin; } + outer.doScrollRight(true); + break; + case MESSAGE_SCROLLDOWN: + outer.mScrollRepeatRate -= (outer.mScrollRepeatRateStep++) * 5; if (outer.mScrollRepeatRate < outer.mScrollRepeatRateMin) { outer.mScrollRepeatRate = outer.mScrollRepeatRateMin; } + outer.doScrollDown(true); + break; + case MESSAGE_SCROLLUP: + outer.mScrollRepeatRate -= (outer.mScrollRepeatRateStep++) * 5; if (outer.mScrollRepeatRate < outer.mScrollRepeatRateMin) { outer.mScrollRepeatRate = outer.mScrollRepeatRateMin; } + outer.doScrollUp(true); + break; + case MESSAGE_STARTSELECTION: + outer.startSelection(msg.arg1, msg.arg2); + break; + case MESSAGE_ENCODINGCHANGED: + outer.updateEncoding((String) msg.obj); + break; + case MESSAGE_SETTINGSCHANGED: + outer.doUpdateSetting(msg.getData().getString("KEY"), msg.getData().getString("VALUE")); + break; + case MESSAGE_CLEARTEXT: + outer.mBuffer.empty(); + outer.mHoldBuffer.empty(); + break; + case MESSAGE_SHUTDOWN: + outer.shutdown(); + break; + case MESSAGE_FLUSHBUFFER: + outer.flushBuffer(); + break; + case MESSAGE_DRAW: + outer.invalidate(); + break; + case MESSAGE_ADDTEXT: + outer.addBytes((byte[]) msg.obj, false); + break; + case MESSAGE_PROCESSXCALLS: + outer.xcallS(msg.getData().getString("FUNCTION"), (String) msg.obj); + break; + case MESSAGE_XCALLB: + try { + outer.xcallB(msg.getData().getString("FUNCTION"), (byte[]) msg.obj); + } catch (LuaException e) { + e.printStackTrace(); + } + break; + default: + break; + } + } + } } From 436fc35a808884c5236d973f7f4d4ad16a671c70 Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 23:09:56 -0400 Subject: [PATCH 03/17] Fix ResourceType lint warnings with @SuppressLint for dynamic view IDs. --- .../bt/alias/AliasSelectionDialog.java | 50 ++++++---- .../bt/timer/TimerSelectionDialog.java | 90 ++++++++--------- .../bt/trigger/TriggerEditorDialog.java | 2 +- .../bt/trigger/TriggerSelectionDialog.java | 99 +++++++++---------- 4 files changed, 125 insertions(+), 116 deletions(-) diff --git a/BTLib/src/com/offsetnull/bt/alias/AliasSelectionDialog.java b/BTLib/src/com/offsetnull/bt/alias/AliasSelectionDialog.java index 6c354b07..be129b6d 100644 --- a/BTLib/src/com/offsetnull/bt/alias/AliasSelectionDialog.java +++ b/BTLib/src/com/offsetnull/bt/alias/AliasSelectionDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.alias; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -14,12 +15,14 @@ import com.offsetnull.bt.validator.Validator; import com.offsetnull.bt.window.AnimatedRelativeLayout; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.KeyEvent; @@ -385,6 +388,7 @@ public AliasAdapter(Context context, int txtviewresid, ArrayList obj this.items = objects; } + @SuppressLint("ResourceType") public View getView(int pos, View convertView, ViewGroup parent) { View v = convertView; if(v == null) { @@ -705,39 +709,48 @@ public void onClick(View v) { } - public final int MSG_DELETEALIAS = 101; - public final int MSG_MODIFYALIAS = 102; - public Handler aliasModifier = new Handler() { + public static final int MSG_DELETEALIAS = 101; + public static final int MSG_MODIFYALIAS = 102; + private static class AliasModifierHandler extends Handler { + private final WeakReference ref; + AliasModifierHandler(AliasSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + @SuppressWarnings("unchecked") public void handleMessage(Message msg) { + AliasSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case MSG_DELETEALIAS: - AliasEntry tmp = apdapter.getItem(msg.arg1); - apdapter.remove(apdapter.getItem(msg.arg1)); + AliasEntry tmp = outer.apdapter.getItem(msg.arg1); + outer.apdapter.remove(outer.apdapter.getItem(msg.arg1)); //check to see if this is an offender - for(int i=0;i existingAliases = (HashMap) service.getAliases(); + + HashMap existingAliases = (HashMap) outer.service.getAliases(); existingAliases.remove(oldKey); - service.setAliases(existingAliases); - + outer.service.setAliases(existingAliases); + //Log.e("ALIASED","DELETING ALIAS"); break; case MSG_MODIFYALIAS: //String tomodify = (String)msg.obj; //String[] parts = tomodify.split("\\Q[||]\\E"); int position = msg.arg1; - AliasEditorDialog diag = new AliasEditorDialog(AliasSelectionDialog.this.getContext(),AliasSelectionDialog.this,((AliasData)msg.obj).getPre(),((AliasData)msg.obj).getPost(),position,(AliasData)msg.obj,service,computeNames(((AliasData)msg.obj).getPre()),currentPlugin); + AliasEditorDialog diag = new AliasEditorDialog(outer.getContext(),outer,((AliasData)msg.obj).getPre(),((AliasData)msg.obj).getPost(),position,(AliasData)msg.obj,outer.service,outer.computeNames(((AliasData)msg.obj).getPre()),outer.currentPlugin); diag.setTitle("Modify Alias:"); diag.show(); break; @@ -745,7 +758,8 @@ public void handleMessage(Message msg) { break; } } - }; + } + public Handler aliasModifier = new AliasModifierHandler(this); ArrayList names = new ArrayList(); @@ -944,7 +958,7 @@ public boolean validateList() { return retval; } - private class AliasComparator implements Comparator { + private static class AliasComparator implements Comparator { public int compare(AliasEntry a, AliasEntry b) { String a_str = a.pre; diff --git a/BTLib/src/com/offsetnull/bt/timer/TimerSelectionDialog.java b/BTLib/src/com/offsetnull/bt/timer/TimerSelectionDialog.java index 2647b528..356e562d 100644 --- a/BTLib/src/com/offsetnull/bt/timer/TimerSelectionDialog.java +++ b/BTLib/src/com/offsetnull/bt/timer/TimerSelectionDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.timer; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -9,12 +10,14 @@ import com.offsetnull.bt.service.StellarService; import com.offsetnull.bt.window.AnimatedRelativeLayout; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; //import android.util.Log; import android.text.TextUtils.TruncateAt; @@ -147,49 +150,7 @@ public void onClick(View v) { }); //set click listeners. - doneHandler = new Handler() { - public void handleMessage(Message msg) { - //do some stuff; - - //if(msg.what == 100) { - - //if(this.hasMessages(100)) { - - //} else { - // this.sendEmptyMessageDelayed(100, 330); - //} - - //} else { - switch(msg.what) { - case 99: - //special editor non new exit, means we need to clear the progress wad of the ordinal. - //wad.remove((String)msg.obj); - buildList(); - break; - case 101: - - //ListView tmp = (ListView) TimerSelectionDialog.this.findViewById(R.id.list); - //tmp.invalidate(); - //adapter.notifyDataSetInvalidated(); - //updateTimers(); - buildList(); - break; - //this.sendEmptyMessageDelayed(101, 1000); - case 100: - //editor new - //button_row.setVisibility(View.VISIBLE); - lastSelectedIndex = Integer.parseInt((String)msg.obj); - buildList(); - break; - case 102: - //button_row.setVisibility(View.INVISIBLE); - break; - default: - break; - } - //} - } - }; + doneHandler = new DoneHandler(this); TextView title = (TextView)findViewById(R.id.titlebar); title.setText("TIMERS"); @@ -273,6 +234,7 @@ public TimerListAdapter(Context context, entries = objects; } + @SuppressLint("ResourceType") public View getView(int pos, View convertView,ViewGroup parent) { View v = convertView; if(v == null) { @@ -759,7 +721,45 @@ public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } - + + } + + private static class DoneHandler extends Handler { + private final WeakReference ref; + DoneHandler(TimerSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(Message msg) { + TimerSelectionDialog outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case 99: + //special editor non new exit, means we need to clear the progress wad of the ordinal. + //wad.remove((String)msg.obj); + outer.buildList(); + break; + case 101: + //ListView tmp = (ListView) TimerSelectionDialog.this.findViewById(R.id.list); + //tmp.invalidate(); + //adapter.notifyDataSetInvalidated(); + //updateTimers(); + outer.buildList(); + break; + //this.sendEmptyMessageDelayed(101, 1000); + case 100: + //editor new + //button_row.setVisibility(View.VISIBLE); + outer.lastSelectedIndex = Integer.parseInt((String)msg.obj); + outer.buildList(); + break; + case 102: + //button_row.setVisibility(View.INVISIBLE); + break; + default: + break; + } + } } - } diff --git a/BTLib/src/com/offsetnull/bt/trigger/TriggerEditorDialog.java b/BTLib/src/com/offsetnull/bt/trigger/TriggerEditorDialog.java index 9a0339b6..66ff28ff 100644 --- a/BTLib/src/com/offsetnull/bt/trigger/TriggerEditorDialog.java +++ b/BTLib/src/com/offsetnull/bt/trigger/TriggerEditorDialog.java @@ -619,7 +619,7 @@ public void onCheckedChanged(CompoundButton arg0, boolean arg1) { v.setText("Regular expressions have been enabled. Unpredictable or poor performance can result from overly broad regular expressions. Please see the documentation for the Java Pattern Class for more information."); int pad = (int) (5.0f * getContext().getResources().getDisplayMetrics().density); - v.setTextAppearance(getContext(), android.R.attr.textAppearanceMedium); + v.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium); v.setTextSize(3*pad); Pattern wikiWordMatcher = Pattern.compile("Java Pattern Class"); String wikiViewURL = ""; diff --git a/BTLib/src/com/offsetnull/bt/trigger/TriggerSelectionDialog.java b/BTLib/src/com/offsetnull/bt/trigger/TriggerSelectionDialog.java index a6ab81b6..7ed115da 100644 --- a/BTLib/src/com/offsetnull/bt/trigger/TriggerSelectionDialog.java +++ b/BTLib/src/com/offsetnull/bt/trigger/TriggerSelectionDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.trigger; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -9,6 +10,7 @@ import com.offsetnull.bt.service.StellarService; import com.offsetnull.bt.window.AnimatedRelativeLayout; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.app.Dialog; import android.app.AlertDialog.Builder; @@ -16,6 +18,7 @@ import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.Gravity; @@ -672,61 +675,50 @@ private void buildList() { adapter.notifyDataSetInvalidated(); } - private Handler triggerEditorDoneHandler = new Handler() { - + private static class TriggerEditorDoneHandler extends Handler { + private final WeakReference ref; + TriggerEditorDoneHandler(TriggerSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + TriggerSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 102: - scrollToSelection(msg.arg1); + outer.scrollToSelection(msg.arg1); break; case 100: //refresh the list because it's done. - //TriggerItem e = adapter.getItem(lastSelectedIndex); TriggerData d = (TriggerData)msg.obj; TriggerItem tmp = new TriggerItem(); tmp.name = d.getName(); tmp.extra = d.getPattern(); tmp.enabled = true; //TODO: set this to the actual setting when implemented. - - list.setFocusable(false); - list.setOnFocusChangeListener(null); - buildList(); - list.setOnFocusChangeListener(new ListFocusFixerListener()); - list.setFocusable(true); + + outer.list.setFocusable(false); + outer.list.setOnFocusChangeListener(null); + outer.buildList(); + outer.list.setOnFocusChangeListener(outer.new ListFocusFixerListener()); + outer.list.setFocusable(true); //re-select the index. - - int index = adapter.getPosition(tmp); + + int index = outer.adapter.getPosition(tmp); this.sendMessageDelayed(this.obtainMessage(102, index, 0),1); - //scrollToSelection(index); - //find the index of the new child. - //View v = list.getChildAt(lastSelectedIndex); - /*list.invalidate(); - - int childcount = list.getChildCount(); - View tmpView = list.getChildAt(index); - list.setSelection(index); - ViewFlipper f = (ViewFlipper)tmpView.findViewById(R.id.flipper); - - f.setInAnimation(new TranslateAnimation(0,0,0,0)); - - f.showNext(); - list.getChildAt(index).findViewById(R.id.toolbar_tab_close).requestFocus();*/ break; case 101: //refresh the list because it's done. - //TriggerItem e = adapter.getItem(lastSelectedIndex); - list.setFocusable(false); - list.setOnFocusChangeListener(null); - buildList(); - list.setOnFocusChangeListener(new ListFocusFixerListener()); - list.setFocusable(true); - - + outer.list.setFocusable(false); + outer.list.setOnFocusChangeListener(null); + outer.buildList(); + outer.list.setOnFocusChangeListener(outer.new ListFocusFixerListener()); + outer.list.setFocusable(true); break; } - } - }; + } + private Handler triggerEditorDoneHandler = new TriggerEditorDoneHandler(this); private class LineClickedListener implements View.OnClickListener { @@ -808,16 +800,17 @@ public TriggerListAdapter(Context context, entries = objects; } + @SuppressLint("ResourceType") public View getView(int pos, View convertView,ViewGroup parent) { View v = convertView; if(v == null) { LayoutInflater li = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = li.inflate(R.layout.editor_selection_list_row,null); - + RelativeLayout root = (RelativeLayout) v.findViewById(R.id.root); root.setOnClickListener(mLineClicker); } - + v.setId(157*pos); RelativeLayout holder = (RelativeLayout)v.findViewById(R.id.toolbarholder); @@ -1063,7 +1056,7 @@ public int compare(TriggerItem a, TriggerItem b) { } - public class TriggerItem { + public static class TriggerItem { public boolean enabled; String name; String extra; @@ -1090,11 +1083,19 @@ public boolean equals(Object o) { public static final int MESSAGE_MOD_TRIGGER = 101; public static final int MESSAGE_DELETE_TRIGGER = 102; - public Handler triggerModifier = new Handler() { + private static class TriggerModifierHandler extends Handler { + private final WeakReference ref; + TriggerModifierHandler(TriggerSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + TriggerSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 104: - finishDelete(); + outer.finishDelete(); break; case 103: //finishScroll(msg.arg1); @@ -1102,28 +1103,22 @@ public void handleMessage(Message msg) { case MESSAGE_NEW_TRIGGER: TriggerData tmp = (TriggerData)msg.obj; //attempt to modify service - - service.newTrigger(tmp); - + outer.service.newTrigger(tmp); break; case MESSAGE_MOD_TRIGGER: TriggerData[] pair = (TriggerData[])msg.obj; TriggerData from = pair[0]; TriggerData to = pair[1]; - - - service.updateTrigger(from, to); - + outer.service.updateTrigger(from, to); break; case MESSAGE_DELETE_TRIGGER: String which = (String)msg.obj; - - service.deleteTrigger(which); - + outer.service.deleteTrigger(which); break; } } - }; + } + public Handler triggerModifier = new TriggerModifierHandler(this); protected void finishDelete() { buildList(); From 175ab1188ccaaf0325b0b19c6d0e3a6697fcbb5c Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 23:10:03 -0400 Subject: [PATCH 04/17] Suppress DiscouragedApi warnings for cross-module resource lookups. --- .../notification/NotificationResponder.java | 3 +++ .../offsetnull/bt/service/StellarService.java | 9 ++++++- .../plugin/settings/BasePluginParser.java | 7 ++++-- .../offsetnull/bt/settings/BaseParser.java | 7 ++++-- .../bt/settings/ConfigurationLoader.java | 5 ++++ .../com/offsetnull/bt/window/AboutDialog.java | 25 ++++++++++--------- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/BTLib/src/com/offsetnull/bt/responder/notification/NotificationResponder.java b/BTLib/src/com/offsetnull/bt/responder/notification/NotificationResponder.java index 3587a4d1..e88c0bd0 100644 --- a/BTLib/src/com/offsetnull/bt/responder/notification/NotificationResponder.java +++ b/BTLib/src/com/offsetnull/bt/responder/notification/NotificationResponder.java @@ -9,6 +9,7 @@ import org.keplerproject.luajava.LuaState; import org.xmlpull.v1.XmlSerializer; +import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -127,6 +128,8 @@ public String getTitle() { //vp[2] = 50; //vp[3] = 200; + // Resource name for notification icon is loaded from configuration at runtime. + @SuppressLint("DiscouragedApi") @Override public boolean doResponse(Context c,TextTree tree,int lineNumber,ListIterator iterator,TextTree.Line line,int start,int end,String matched,Object source,String displayname,String host,int port,int triggernumber,boolean windowIsOpen,Handler dispatcher,HashMap captureMap,LuaState L,String name,String encoding) { //we are going to do the window response now. diff --git a/BTLib/src/com/offsetnull/bt/service/StellarService.java b/BTLib/src/com/offsetnull/bt/service/StellarService.java index dbb1d5a2..617e11c4 100644 --- a/BTLib/src/com/offsetnull/bt/service/StellarService.java +++ b/BTLib/src/com/offsetnull/bt/service/StellarService.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Map; +import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -307,8 +308,10 @@ public final void doVibrateBell() { * @param host The host name of the calling connection. * @param port The port number for the calling connection. */ + // Resource name for notification icon is loaded from configuration at runtime. + @SuppressLint("DiscouragedApi") @SuppressWarnings("deprecation") - public final void doNotifyBell(final String display, final String host, final int port) { + public final void doNotifyBell(final String display, final String host, final int port) { int resId = this.getResources().getIdentifier(ConfigurationLoader.getConfigurationValue("notificationIcon", this.getApplicationContext()), "drawable", this.getPackageName()); //Notification note = new Notification(resId, "Alert!", System.currentTimeMillis()); @@ -394,6 +397,8 @@ public static int getNotificationId() { * @param host The host name associated with c * @param port The port name associated with c */ + // Resource name for notification icon is loaded from configuration at runtime. + @SuppressLint("DiscouragedApi") @SuppressWarnings("deprecation") private void showDisconnectedNotification(final Connection c, final String display, final String host, final int port) { //if we are here it means that the server has explicitly closed the connection, and nobody was around to see it. @@ -471,6 +476,8 @@ private void showDisconnectedNotification(final Connection c, final String displ * @param host The host name of the connection. * @param port The port number of the connection. */ + // Resource name for notification icon is loaded from configuration at runtime. + @SuppressLint("DiscouragedApi") @SuppressWarnings("deprecation") public final void showConnectionNotification(final String display, final String host, final int port) { if (mConnectionNotificationMap.containsKey(display)) { return; } diff --git a/BTLib/src/com/offsetnull/bt/service/plugin/settings/BasePluginParser.java b/BTLib/src/com/offsetnull/bt/service/plugin/settings/BasePluginParser.java index aa872db6..54522323 100644 --- a/BTLib/src/com/offsetnull/bt/service/plugin/settings/BasePluginParser.java +++ b/BTLib/src/com/offsetnull/bt/service/plugin/settings/BasePluginParser.java @@ -4,6 +4,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; +import android.annotation.SuppressLint; import android.content.Context; import android.os.Environment; @@ -90,11 +91,13 @@ protected BasePluginParser(String location,Context context) { path = location; } + // Resource is in the app module, not this library, so getIdentifier is required. + @SuppressLint("DiscouragedApi") protected InputStream getInputStream() throws FileNotFoundException { FileInputStream input = null; - + if(path == null) { - return mContext.getResources().openRawResource(mContext.getResources().getIdentifier("default_settings", "raw", mContext.getPackageName())); + return mContext.getResources().openRawResource(mContext.getResources().getIdentifier("default_settings", "raw", mContext.getPackageName())); } if(path.contains(Environment.getExternalStorageDirectory().getPath())) { diff --git a/BTLib/src/com/offsetnull/bt/settings/BaseParser.java b/BTLib/src/com/offsetnull/bt/settings/BaseParser.java index 98c41829..d8389cb1 100644 --- a/BTLib/src/com/offsetnull/bt/settings/BaseParser.java +++ b/BTLib/src/com/offsetnull/bt/settings/BaseParser.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.util.List; +import android.annotation.SuppressLint; import android.content.Context; import android.os.Environment; @@ -167,10 +168,12 @@ protected BaseParser(String location,Context context) { } + // Resource is in the app module, not this library, so getIdentifier is required. + @SuppressLint("DiscouragedApi") protected InputStream getInputStream() throws FileNotFoundException { - + FileInputStream input = null; - + if(path == null) { return mContext.getResources().openRawResource(mContext.getResources().getIdentifier("default_settings", "raw", mContext.getPackageName())); } diff --git a/BTLib/src/com/offsetnull/bt/settings/ConfigurationLoader.java b/BTLib/src/com/offsetnull/bt/settings/ConfigurationLoader.java index 31a67446..00f95b97 100644 --- a/BTLib/src/com/offsetnull/bt/settings/ConfigurationLoader.java +++ b/BTLib/src/com/offsetnull/bt/settings/ConfigurationLoader.java @@ -1,14 +1,19 @@ package com.offsetnull.bt.settings; +import android.annotation.SuppressLint; import android.content.Context; public class ConfigurationLoader { + // Resource name is determined at runtime by callers, so getIdentifier is required. + @SuppressLint("DiscouragedApi") public static String getConfigurationValue(String key, Context context) { int id = context.getResources().getIdentifier(key, "string", context.getPackageName()); return context.getResources().getString(id); } + // Resource is in the app module, not this library, so getIdentifier is required. + @SuppressLint("DiscouragedApi") public static int getAboutDialogResource(Context context) { int id = context.getResources().getIdentifier("about_dialog", "layout", context.getPackageName()); return id; diff --git a/BTLib/src/com/offsetnull/bt/window/AboutDialog.java b/BTLib/src/com/offsetnull/bt/window/AboutDialog.java index 4f4febf2..31a9290f 100644 --- a/BTLib/src/com/offsetnull/bt/window/AboutDialog.java +++ b/BTLib/src/com/offsetnull/bt/window/AboutDialog.java @@ -1,8 +1,8 @@ package com.offsetnull.bt.window; -import com.offsetnull.bt.R; import com.offsetnull.bt.settings.ConfigurationLoader; +import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.Intent; @@ -17,14 +17,16 @@ public class AboutDialog extends Dialog { public AboutDialog(Context context) { super(context); - + } - + + // Resource IDs are in the app module, not this library, so getIdentifier is required. + @SuppressLint("DiscouragedApi") public void onCreate(Bundle b) { super.onCreate(b); - + this.getWindow().requestFeature(Window.FEATURE_NO_TITLE); - + this.setContentView(ConfigurationLoader.getAboutDialogResource(this.getContext())); try { @@ -33,30 +35,29 @@ public void onCreate(Bundle b) { TextView v = (TextView) this.findViewById(abtid); v.setText("BlowTorch " + str); } catch (NameNotFoundException e) { - // TODO Auto-generated catch block e.printStackTrace(); } - + int aardid = this.getContext().getResources().getIdentifier("aardwolf_button", "id", this.getContext().getPackageName()); if(aardid != 0) { this.findViewById(aardid).setOnClickListener(new View.OnClickListener() { - + public void onClick(View v) { Intent web_help = new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.aardmud.org/")); AboutDialog.this.getContext().startActivity(web_help); } }); } - - int btid = this.getContext().getResources().getIdentifier("blowtorch_button", "id", this.getContext().getPackageName()); + + int btid = this.getContext().getResources().getIdentifier("blowtorch_button", "id", this.getContext().getPackageName()); this.findViewById(btid).setOnClickListener(new View.OnClickListener() { - + public void onClick(View v) { Intent web_help = new Intent(Intent.ACTION_VIEW,Uri.parse("http://bt.happygoatstudios.com/")); AboutDialog.this.getContext().startActivity(web_help); } }); - + //setup links } From e811cc01cef47eff281171229de315c658eb69aa Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 23:10:11 -0400 Subject: [PATCH 05/17] Replace anonymous Handlers with static inner classes to fix memory leaks. --- BTLib/lint-baseline.xml | 209 --------- .../bt/alias/BetterAliasSelectionDialog.java | 21 +- .../bt/button/ButtonSetSelectorDialog.java | 27 +- .../com/offsetnull/bt/launcher/Launcher.java | 397 ++++++++---------- .../offsetnull/bt/service/plugin/Plugin.java | 33 +- .../bt/settings/HyperSettingsActivity.java | 17 +- .../bt/timer/BetterTimerSelectionDialog.java | 21 +- .../trigger/BetterTriggerSelectionDialog.java | 21 +- .../com/offsetnull/bt/window/MainWindow.java | 7 + .../bt/window/PluginSelectorDialog.java | 21 +- 10 files changed, 295 insertions(+), 479 deletions(-) diff --git a/BTLib/lint-baseline.xml b/BTLib/lint-baseline.xml index 9913fd1f..c159e5ef 100644 --- a/BTLib/lint-baseline.xml +++ b/BTLib/lint-baseline.xml @@ -4488,215 +4488,6 @@ column="6"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ref; + AliasEditorDoneHandler(BetterAliasSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + BetterAliasSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 100: AliasData d = (AliasData)msg.obj; - BetterAliasSelectionDialog.this.buildList(); - BetterAliasSelectionDialog.this.scrollToSelection(d.getPre()); + outer.buildList(); + outer.scrollToSelection(d.getPre()); break; } - } - }; + } + private final Handler aliasEditorDoneHandler = new AliasEditorDoneHandler(this); private ArrayList names = new ArrayList(); private List computeNames(String name) { diff --git a/BTLib/src/com/offsetnull/bt/button/ButtonSetSelectorDialog.java b/BTLib/src/com/offsetnull/bt/button/ButtonSetSelectorDialog.java index 3037b7d3..f0983c8b 100644 --- a/BTLib/src/com/offsetnull/bt/button/ButtonSetSelectorDialog.java +++ b/BTLib/src/com/offsetnull/bt/button/ButtonSetSelectorDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.button; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Comparator; @@ -17,6 +18,7 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.KeyEvent; @@ -756,24 +758,30 @@ public void onClick(View v) { } boolean setSettingsHaveChanged = false; - private Handler editordonelistenr = new Handler() { + private static class EditorDoneHandler extends Handler { + private final WeakReference ref; + EditorDoneHandler(ButtonSetSelectorDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + ButtonSetSelectorDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 104: - finishDelete(); + outer.finishDelete(); break; case 100: //entry no name change; //int index = lastSelectedIndex; - setSettingsHaveChanged = true; - ButtonSetSelectorDialog.this.buildList(); + outer.setSettingsHaveChanged = true; + outer.buildList(); break; case 101: //edited entry; - - setSettingsHaveChanged = true; - ButtonSetSelectorDialog.this.buildList(); - + outer.setSettingsHaveChanged = true; + outer.buildList(); break; } //handle the thing comin back; @@ -781,7 +789,8 @@ public void handleMessage(Message msg) { //Log.e("EDITOR","REBUILDING LIST"); } - }; + } + private Handler editordonelistenr = new EditorDoneHandler(this); protected void finishDelete() { buildList(); diff --git a/BTLib/src/com/offsetnull/bt/launcher/Launcher.java b/BTLib/src/com/offsetnull/bt/launcher/Launcher.java index dd9611ea..55080777 100644 --- a/BTLib/src/com/offsetnull/bt/launcher/Launcher.java +++ b/BTLib/src/com/offsetnull/bt/launcher/Launcher.java @@ -52,6 +52,7 @@ import android.os.Environment; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import androidx.core.app.ActivityCompat; import androidx.appcompat.app.AppCompatActivity; @@ -167,60 +168,7 @@ public void onCreate(Bundle icicle) { this.finish(); }*/ - actionHandler = new Handler() { - public void handleMessage(Message msg) { - switch(msg.what) { - case MESSAGE_USERNAME: - SharedPreferences.Editor edit = Launcher.this.getSharedPreferences("TEST_USER", Context.MODE_PRIVATE).edit(); - edit.putString("USER_NAME", (String)msg.obj); - edit.commit(); - break; - case MESSAGE_WHATSNEW: - break; - case MESSAGE_IMPORT: - - //if the file exists, we will get here, if not, it will go to file not found. - try { - LauncherSAXParser parser = new LauncherSAXParser((String)msg.obj,Launcher.this); - launcher_settings = parser.load(); - } catch (RuntimeException e) { - AlertDialog.Builder error = new AlertDialog.Builder(Launcher.this); - error.setTitle("Error loading XML"); - error.setMessage(e.getMessage()); - error.setPositiveButton("Acknowledge.",new DialogInterface.OnClickListener() { - - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - AlertDialog errordialog = error.create(); - errordialog.show(); - return; - } - //update this list to the new version. - PackageManager m = Launcher.this.getPackageManager(); - String versionString = null; - try { - versionString = m.getPackageInfo(Launcher.this.getApplicationInfo().packageName, PackageManager.GET_CONFIGURATIONS).versionName; - } catch (NameNotFoundException e) { - //can't execute on our package aye? - throw new RuntimeException(e); - } - launcher_settings.setCurrentVersion(versionString); - buildList(); - saveXML(); - break; - case MESSAGE_EXPORT: - - break; - case MESSAGE_DORECOVERY: - - break; - default: - break; - } - } - }; + actionHandler = new ActionHandler(this); setContentView(R.layout.new_launcher_layout); androidx.appcompat.widget.Toolbar myToolbar = (androidx.appcompat.widget.Toolbar) findViewById(R.id.my_toolbar); @@ -1576,176 +1524,18 @@ public View getView(int position, View convertView, ViewGroup parent) { } - private final int MESSAGE_STARTUPDATE = 10098; - private final int MESSAGE_STARTDOWNLOAD = 10099; - private final int MESSAGE_CANCELDOWNLOAD = 10100; - private final int MESSAGE_FINISHUPDATE = 10101; - private final int MESSAGE_DOWNLOADEDBYTES = 10102; - private final int MESSAGE_UPTODATE = 10103; - private final int MESSAGE_NOSDCARD = 10104; - private final int MESSAGE_BYTESINCOMING = 10105; - private final int MESSAGE_NEEDSUPDATE = 10106; + private static final int MESSAGE_STARTUPDATE = 10098; + private static final int MESSAGE_STARTDOWNLOAD = 10099; + private static final int MESSAGE_CANCELDOWNLOAD = 10100; + private static final int MESSAGE_FINISHUPDATE = 10101; + private static final int MESSAGE_DOWNLOADEDBYTES = 10102; + private static final int MESSAGE_UPTODATE = 10103; + private static final int MESSAGE_NOSDCARD = 10104; + private static final int MESSAGE_BYTESINCOMING = 10105; + private static final int MESSAGE_NEEDSUPDATE = 10106; ProgressDialog updateDialog = null; UpdateThread update = null; - Handler updateHandler = new Handler() { - public void handleMessage(Message msg) { - switch(msg.what) { - case MESSAGE_NEEDSUPDATE: - AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this); - builder.setTitle("Update Available"); - builder.setMessage("An update is available for this package, would you like to update now?"); - builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - UpdateThread t = new UpdateThread(updateHandler); - t.start(); - dialog.dismiss(); - } - }); - builder.setNegativeButton("No",new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - - }); - AlertDialog d = builder.create(); - d.show(); - break; - case MESSAGE_BYTESINCOMING: - updateDialog.setMessage("Downloading "+(Integer)msg.obj+"bytes."); - updateDialog.setMax((Integer)msg.obj); - break; - case MESSAGE_DOWNLOADEDBYTES: - updateDialog.incrementProgressBy(msg.arg1); - break; - case MESSAGE_STARTUPDATE: - updateDialog = ProgressDialog.show(Launcher.this,"","Checking update status.",true,true,new DialogInterface.OnCancelListener() { - - @Override - public void onCancel(DialogInterface dialog) { - return; - } - }); - break; - case MESSAGE_NOSDCARD: - Toast nodsd = Toast.makeText(Launcher.this, "External storage is unavailable to write to, cannot download update.", Toast.LENGTH_SHORT); - nodsd.show(); - break; - case MESSAGE_UPTODATE: - //Integer newVersion = Integer.parseInt(buf.toString()); - //Log.e("BlowTorch","Web update version: " + newVersion); - updateDialog.dismiss(); - - ApplicationInfo testLauncher = null; - try { - testLauncher = Launcher.this.getPackageManager().getApplicationInfo(launcher_source, PackageManager.GET_META_DATA); - } catch (NameNotFoundException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - int testversionName = testLauncher.metaData.getInt("BLOWTORCH_TEST_VERSION"); - - Toast t = Toast.makeText(Launcher.this, "BlowTorch Test Version "+testversionName+" is up to date.", Toast.LENGTH_SHORT); - t.show(); - break; - case MESSAGE_STARTDOWNLOAD: - - updateDialog.dismiss(); - updateDialog = null; - - updateDialog = new ProgressDialog(Launcher.this); - updateDialog.setCancelable(true); - updateDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - updateDialog.setMessage("Starting download."); - updateDialog.setCancelMessage(this.obtainMessage(MESSAGE_CANCELDOWNLOAD)); - //updateDialog.setMax(size); - //updateDialog.setProgress(0); - updateDialog.show(); - - - -// synchronized(this) { -// try { -// -// this.wait(50); -// } catch (InterruptedException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } - /*URL updateSize; - try { - updateSize = new URL("http://bt.happygoatstudios.com/test/size"); - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - BufferedReader in; - try { - in = new BufferedReader(new InputStreamReader(updateSize.openStream())); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - String tmp = ""; - StringBuffer buf = new StringBuffer(); - try { - while((tmp = in.readLine())!=null) { - buf.append(tmp); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return; - } - Integer size = Integer.parseInt(buf.toString()); - Log.e("BlowTorch","Update size is: " + size + " bytes.");*/ - - - - - //update = new UpdateThread(this); - //update.run(); - - - break; - case MESSAGE_CANCELDOWNLOAD: - update.doCancel(); - if(updateDialog != null) { - updateDialog.dismiss(); - } - updateDialog = null; - String delyou = Environment.getExternalStorageDirectory().getAbsolutePath() + "/BlowTorch/launcher/TestPackage.apk"; - //proceed with download. - File delme = new File(delyou); - if(delme.exists()) delme.delete(); - break; - case MESSAGE_FINISHUPDATE: - updateDialog.dismiss(); - updateDialog = null; - update = null; - String updatepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/BlowTorch/launcher/TestPackage.apk"; - File file = new File(updatepath); - if(!file.exists()) { - //Log.e("BlowTorch","Test application update does not exist."); - return; //file doesn't exist - } - - Intent i = new Intent(); - i.setAction(Intent.ACTION_VIEW); - Uri data = Uri.parse("file://" + updatepath); - i.setDataAndType(data, "application/vnd.android.package-archive"); - startActivity(i); - Launcher.this.finish(); - break; - } - } - }; + Handler updateHandler = new UpdateHandler(this); private class UpdateThread extends Thread { @@ -2043,6 +1833,7 @@ private static class ConnectionModifierHandler extends Handler { private final WeakReference mActivity; ConnectionModifierHandler(Launcher activity) { + super(Looper.getMainLooper()); mActivity = new WeakReference<>(activity); } @@ -2068,4 +1859,166 @@ public void handleMessage(Message msg) { } } } + + private static class ActionHandler extends Handler { + private final WeakReference ref; + ActionHandler(Launcher outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(Message msg) { + Launcher outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case MESSAGE_USERNAME: + SharedPreferences.Editor edit = outer.getSharedPreferences("TEST_USER", Context.MODE_PRIVATE).edit(); + edit.putString("USER_NAME", (String)msg.obj); + edit.commit(); + break; + case MESSAGE_WHATSNEW: + break; + case MESSAGE_IMPORT: + //if the file exists, we will get here, if not, it will go to file not found. + try { + LauncherSAXParser parser = new LauncherSAXParser((String)msg.obj,outer); + outer.launcher_settings = parser.load(); + } catch (RuntimeException e) { + AlertDialog.Builder error = new AlertDialog.Builder(outer); + error.setTitle("Error loading XML"); + error.setMessage(e.getMessage()); + error.setPositiveButton("Acknowledge.",new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + AlertDialog errordialog = error.create(); + errordialog.show(); + return; + } + //update this list to the new version. + PackageManager m = outer.getPackageManager(); + String versionString = null; + try { + versionString = m.getPackageInfo(outer.getApplicationInfo().packageName, PackageManager.GET_CONFIGURATIONS).versionName; + } catch (NameNotFoundException e) { + //can't execute on our package aye? + throw new RuntimeException(e); + } + outer.launcher_settings.setCurrentVersion(versionString); + outer.buildList(); + outer.saveXML(); + break; + case MESSAGE_EXPORT: + break; + case MESSAGE_DORECOVERY: + break; + default: + break; + } + } + } + + private static class UpdateHandler extends Handler { + private final WeakReference ref; + UpdateHandler(Launcher outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(Message msg) { + final Launcher outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case MESSAGE_NEEDSUPDATE: + AlertDialog.Builder builder = new AlertDialog.Builder(outer); + builder.setTitle("Update Available"); + builder.setMessage("An update is available for this package, would you like to update now?"); + builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + UpdateThread t = outer.new UpdateThread(outer.updateHandler); + t.start(); + dialog.dismiss(); + } + }); + builder.setNegativeButton("No",new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + AlertDialog d = builder.create(); + d.show(); + break; + case MESSAGE_BYTESINCOMING: + outer.updateDialog.setMessage("Downloading "+(Integer)msg.obj+"bytes."); + outer.updateDialog.setMax((Integer)msg.obj); + break; + case MESSAGE_DOWNLOADEDBYTES: + outer.updateDialog.incrementProgressBy(msg.arg1); + break; + case MESSAGE_STARTUPDATE: + outer.updateDialog = ProgressDialog.show(outer,"","Checking update status.",true,true,new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + return; + } + }); + break; + case MESSAGE_NOSDCARD: + Toast nodsd = Toast.makeText(outer, "External storage is unavailable to write to, cannot download update.", Toast.LENGTH_SHORT); + nodsd.show(); + break; + case MESSAGE_UPTODATE: + outer.updateDialog.dismiss(); + ApplicationInfo testLauncher = null; + try { + testLauncher = outer.getPackageManager().getApplicationInfo(outer.launcher_source, PackageManager.GET_META_DATA); + } catch (NameNotFoundException e1) { + e1.printStackTrace(); + } + int testversionName = testLauncher.metaData.getInt("BLOWTORCH_TEST_VERSION"); + Toast t = Toast.makeText(outer, "BlowTorch Test Version "+testversionName+" is up to date.", Toast.LENGTH_SHORT); + t.show(); + break; + case MESSAGE_STARTDOWNLOAD: + outer.updateDialog.dismiss(); + outer.updateDialog = null; + outer.updateDialog = new ProgressDialog(outer); + outer.updateDialog.setCancelable(true); + outer.updateDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + outer.updateDialog.setMessage("Starting download."); + outer.updateDialog.setCancelMessage(outer.updateHandler.obtainMessage(MESSAGE_CANCELDOWNLOAD)); + outer.updateDialog.show(); + break; + case MESSAGE_CANCELDOWNLOAD: + outer.update.doCancel(); + if(outer.updateDialog != null) { + outer.updateDialog.dismiss(); + } + outer.updateDialog = null; + String delyou = Environment.getExternalStorageDirectory().getAbsolutePath() + "/BlowTorch/launcher/TestPackage.apk"; + File delme = new File(delyou); + if(delme.exists()) delme.delete(); + break; + case MESSAGE_FINISHUPDATE: + outer.updateDialog.dismiss(); + outer.updateDialog = null; + outer.update = null; + String updatepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/BlowTorch/launcher/TestPackage.apk"; + File file = new File(updatepath); + if(!file.exists()) { + return; //file doesn't exist + } + Intent i = new Intent(); + i.setAction(Intent.ACTION_VIEW); + Uri data = Uri.parse("file://" + updatepath); + i.setDataAndType(data, "application/vnd.android.package-archive"); + outer.startActivity(i); + outer.finish(); + break; + } + } + } } diff --git a/BTLib/src/com/offsetnull/bt/service/plugin/Plugin.java b/BTLib/src/com/offsetnull/bt/service/plugin/Plugin.java index f3c20867..23ed30a4 100644 --- a/BTLib/src/com/offsetnull/bt/service/plugin/Plugin.java +++ b/BTLib/src/com/offsetnull/bt/service/plugin/Plugin.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -35,6 +36,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.util.Log; @@ -137,15 +139,7 @@ public Plugin(PluginSettings settings,Handler h,ConnectionPluginCallback parent, HashMap timerStartTimes; public void initTimers() { - innerHandler = new Handler() { - public void handleMessage(Message msg) { - switch(msg.what) { - case 100: - DoTimerResponders((String)msg.obj); - break; - } - } - }; + innerHandler = new InnerHandler(this); timerStartTimes = new HashMap(); CONNECTION_TIMER = new Timer("blowtorch_"+this.getName()+"_timer",true); @@ -3108,8 +3102,21 @@ public String getOptionValue(String key) { return g.getOptionValue(key); } - - - - + private static class InnerHandler extends Handler { + private final WeakReference ref; + InnerHandler(Plugin outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override + public void handleMessage(Message msg) { + Plugin outer = ref.get(); + if (outer == null) return; + switch(msg.what) { + case 100: + outer.DoTimerResponders((String)msg.obj); + break; + } + } + } } diff --git a/BTLib/src/com/offsetnull/bt/settings/HyperSettingsActivity.java b/BTLib/src/com/offsetnull/bt/settings/HyperSettingsActivity.java index 636a2253..8fafeaf7 100644 --- a/BTLib/src/com/offsetnull/bt/settings/HyperSettingsActivity.java +++ b/BTLib/src/com/offsetnull/bt/settings/HyperSettingsActivity.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.FilenameFilter; +import java.lang.ref.WeakReference; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; @@ -19,6 +20,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.preference.EditTextPreference; import android.preference.ListPreference; @@ -247,12 +249,21 @@ public void onStart() { //Log.e("KLSDF","STARTING ONSTART"); } - public Handler importexport = new Handler() { + private static class ImportExportHandler extends Handler { + private final WeakReference ref; + ImportExportHandler(HyperSettingsActivity outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + HyperSettingsActivity outer = ref.get(); + if (outer == null) return; //we only get one message, so we do the dumpout. - dumpout(); + outer.dumpout(); } - }; + } + public Handler importexport = new ImportExportHandler(this); public void onBackPressed() { dumpout(); diff --git a/BTLib/src/com/offsetnull/bt/timer/BetterTimerSelectionDialog.java b/BTLib/src/com/offsetnull/bt/timer/BetterTimerSelectionDialog.java index d9ec0211..a63213a3 100644 --- a/BTLib/src/com/offsetnull/bt/timer/BetterTimerSelectionDialog.java +++ b/BTLib/src/com/offsetnull/bt/timer/BetterTimerSelectionDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.timer; +import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -12,6 +13,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; @@ -236,19 +238,26 @@ public void willHideToolbar(LinearLayout toolbar,int row) { } - private final Handler triggerEditorDoneHandler = new Handler() { - + private static class TimerEditorDoneHandler extends Handler { + private final WeakReference ref; + TimerEditorDoneHandler(BetterTimerSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + BetterTimerSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 100: TimerData d = (TimerData)msg.obj; - BetterTimerSelectionDialog.this.buildList(); - BetterTimerSelectionDialog.this.scrollToSelection(d.getName()); + outer.buildList(); + outer.scrollToSelection(d.getName()); break; } - } - }; + } + private final Handler triggerEditorDoneHandler = new TimerEditorDoneHandler(this); diff --git a/BTLib/src/com/offsetnull/bt/trigger/BetterTriggerSelectionDialog.java b/BTLib/src/com/offsetnull/bt/trigger/BetterTriggerSelectionDialog.java index 7cbcb8ee..08b0e228 100644 --- a/BTLib/src/com/offsetnull/bt/trigger/BetterTriggerSelectionDialog.java +++ b/BTLib/src/com/offsetnull/bt/trigger/BetterTriggerSelectionDialog.java @@ -1,5 +1,6 @@ package com.offsetnull.bt.trigger; +import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -8,6 +9,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; @@ -163,19 +165,26 @@ public void willShowToolbar(LinearLayout toolbar, int row) { } } -private final Handler triggerEditorDoneHandler = new Handler() { - +private static class TriggerEditorDoneHandler extends Handler { + private final WeakReference ref; + TriggerEditorDoneHandler(BetterTriggerSelectionDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { + BetterTriggerSelectionDialog outer = ref.get(); + if (outer == null) return; switch(msg.what) { case 100: TriggerData d = (TriggerData)msg.obj; - BetterTriggerSelectionDialog.this.buildList(); - BetterTriggerSelectionDialog.this.scrollToSelection(d.getName()); + outer.buildList(); + outer.scrollToSelection(d.getName()); break; } - } - }; + } +private final Handler triggerEditorDoneHandler = new TriggerEditorDoneHandler(this); @Override public void willHideToolbar(LinearLayout v, int row) { diff --git a/BTLib/src/com/offsetnull/bt/window/MainWindow.java b/BTLib/src/com/offsetnull/bt/window/MainWindow.java index 2d7c4e45..6fb17e58 100644 --- a/BTLib/src/com/offsetnull/bt/window/MainWindow.java +++ b/BTLib/src/com/offsetnull/bt/window/MainWindow.java @@ -25,6 +25,7 @@ import org.keplerproject.luajava.LuaStateFactory; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; @@ -55,6 +56,7 @@ import android.os.Environment; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import android.preference.PreferenceManager; import com.google.android.material.snackbar.Snackbar; @@ -342,6 +344,7 @@ public void onServiceDisconnected(ComponentName arg0) { private int titleBarHeight; //private LayerManager mLayers = null; + @SuppressLint("ResourceType") public void onCreate(Bundle icicle) { //Log.e("Window","start onCreate"); //Debug.startMethodTracing("window"); @@ -2977,6 +2980,7 @@ public void initiailizeWindows() { //Debug.stopMethodTracing(); } + @SuppressLint("ResourceType") private void initWindow(WindowToken w,String dataDir) { RelativeLayout rl = (RelativeLayout)this.findViewById(R.id.window_container); View v = rl.findViewWithTag(w.getName()); @@ -3045,6 +3049,7 @@ private void initWindow(WindowToken w,String dataDir) { } + @SuppressLint("ResourceType") public void cleanupWindows() { RelativeLayout rl = (RelativeLayout)this.findViewById(R.id.window_container); if(mWindows == null) return; @@ -3291,6 +3296,7 @@ private static class MainWindowHandler extends Handler { private final WeakReference mActivity; MainWindowHandler(MainWindow activity) { + super(Looper.getMainLooper()); mActivity = new WeakReference<>(activity); } @@ -3308,6 +3314,7 @@ private static class ExportHandler extends Handler { private final WeakReference mActivity; ExportHandler(MainWindow activity) { + super(Looper.getMainLooper()); mActivity = new WeakReference<>(activity); } diff --git a/BTLib/src/com/offsetnull/bt/window/PluginSelectorDialog.java b/BTLib/src/com/offsetnull/bt/window/PluginSelectorDialog.java index da8e6100..285a2088 100644 --- a/BTLib/src/com/offsetnull/bt/window/PluginSelectorDialog.java +++ b/BTLib/src/com/offsetnull/bt/window/PluginSelectorDialog.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.lang.ref.WeakReference; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Comparator; @@ -27,6 +28,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; @@ -529,14 +531,23 @@ public void onClick(View v) { } - private Handler dismissTimer = new Handler() { + private static class DismissTimerHandler extends Handler { + private final WeakReference ref; + DismissTimerHandler(PluginSelectorDialog outer) { + super(Looper.getMainLooper()); + ref = new WeakReference<>(outer); + } + @Override public void handleMessage(Message msg) { - Toast t = Toast.makeText(PluginSelectorDialog.this.getContext(), "Adding plugin and reloading settings.",Toast.LENGTH_LONG); - PluginSelectorDialog.this.dismiss(); - PluginSelectorDialog.this.mListener.onPluginLoad(); + PluginSelectorDialog outer = ref.get(); + if (outer == null) return; + Toast t = Toast.makeText(outer.getContext(), "Adding plugin and reloading settings.",Toast.LENGTH_LONG); + outer.dismiss(); + outer.mListener.onPluginLoad(); t.show(); } - }; + } + private Handler dismissTimer = new DismissTimerHandler(this); public interface OnPluginLoadListener { public void onPluginLoad(); From 37ea3519930d2524ff73ef30fc72fa00a90c72b0 Mon Sep 17 00:00:00 2001 From: James Power Date: Mon, 9 Mar 2026 23:42:26 -0400 Subject: [PATCH 06/17] Fix XML layout lint warnings across all layout variants. --- BTLib/lint-baseline.xml | 1312 +---------------- .../layout-land/button_properties_dialog.xml | 24 +- .../button_properties_dialog_tabbed.xml | 46 +- .../buttonset_selection_dialog.xml | 10 +- .../buttonset_selection_list_row.xml | 2 +- .../buttonset_settings_editor_dialog.xml | 32 +- BTLib/res/layout-land/connection_row.xml | 2 +- BTLib/res/layout-land/conpickerdialog.xml | 8 +- BTLib/res/layout-land/dialog_text_entry.xml | 10 +- BTLib/res/layout-land/new_buttonset_entry.xml | 2 +- BTLib/res/layout-land/new_launcher_layout.xml | 16 +- BTLib/res/layout-land/newconnectiondialog.xml | 28 +- BTLib/res/layout-land/number_setting_row.xml | 12 +- .../plugin_info_dialog_list_row.xml | 6 +- .../plugin_infod_dialog_list_row.xml | 6 +- .../res/layout-land/responder_ack_dialog.xml | 6 +- .../responder_notification_dialog.xml | 56 +- .../layout-land/responder_toast_dialog.xml | 8 +- BTLib/res/layout-land/seekbar_widget.xml | 2 +- .../layout-land/settings_editor_layout.xml | 4 +- BTLib/res/layout-land/timer_editor_dialog.xml | 46 +- .../layout-land/timer_selection_dialog.xml | 14 +- .../layout-land/timer_selection_list_row.xml | 30 +- .../res/layout-land/trigger_editor_dialog.xml | 40 +- BTLib/res/layout-land/window_layout.xml | 14 +- .../editor_selection_dialog.xml | 20 +- .../layout-sw600dp/responder_gag_dialog.xml | 6 +- .../layout-sw600dp/timer_editor_dialog.xml | 46 +- .../layout-sw600dp/trigger_editor_dialog.xml | 40 +- BTLib/res/layout-sw600dp/window_layout.xml | 8 +- .../layout-xlarge/editor_selection_dialog.xml | 20 +- .../layout-xlarge/responder_gag_dialog.xml | 6 +- .../res/layout-xlarge/timer_editor_dialog.xml | 46 +- .../layout-xlarge/trigger_editor_dialog.xml | 40 +- BTLib/res/layout-xlarge/window_layout.xml | 8 +- BTLib/res/layout/alias_dialog.xml | 14 +- BTLib/res/layout/alias_row.xml | 2 +- BTLib/res/layout/better_list_row.xml | 28 +- BTLib/res/layout/better_selection_dialog.xml | 10 +- BTLib/res/layout/button_properties_dialog.xml | 24 +- .../button_properties_dialog_tabbed.xml | 46 +- .../res/layout/buttonset_selection_dialog.xml | 10 +- .../layout/buttonset_selection_list_row.xml | 2 +- .../buttonset_settings_editor_dialog.xml | 32 +- BTLib/res/layout/connection_row.xml | 2 +- BTLib/res/layout/conpickerdialog.xml | 8 +- BTLib/res/layout/dialog_text_entry.xml | 10 +- BTLib/res/layout/editor_selection_dialog.xml | 20 +- .../editor_selection_filter_divider_row.xml | 2 +- .../editor_selection_filter_list_row.xml | 4 +- .../res/layout/editor_selection_list_row.xml | 40 +- BTLib/res/layout/new_alias_dialog.xml | 56 +- BTLib/res/layout/new_buttonset_entry.xml | 2 +- BTLib/res/layout/new_launcher_layout.xml | 16 +- BTLib/res/layout/newconnectiondialog.xml | 28 +- BTLib/res/layout/number_setting_row.xml | 12 +- BTLib/res/layout/options_list_row.xml | 6 +- .../layout/plugin_info_dialog_list_row.xml | 6 +- BTLib/res/layout/plugin_search_list_row.xml | 6 +- BTLib/res/layout/plugins_dialog.xml | 14 +- .../preference_checkededitor_widget.xml | 8 +- BTLib/res/layout/responder_ack_dialog.xml | 6 +- BTLib/res/layout/responder_color_dialog.xml | 8 +- BTLib/res/layout/responder_gag_dialog.xml | 6 +- .../layout/responder_notification_dialog.xml | 56 +- BTLib/res/layout/responder_script_dialog.xml | 6 +- BTLib/res/layout/responder_toast_dialog.xml | 8 +- BTLib/res/layout/seekbar_widget.xml | 2 +- BTLib/res/layout/settings_editor_layout.xml | 4 +- BTLib/res/layout/speedwalk_dialog.xml | 8 +- .../layout/speedwalk_new_direction_dialog.xml | 20 +- BTLib/res/layout/speedwalk_row.xml | 4 +- BTLib/res/layout/timer_editor_dialog.xml | 46 +- BTLib/res/layout/timer_selection_dialog.xml | 14 +- BTLib/res/layout/timer_selection_list_row.xml | 30 +- BTLib/res/layout/trigger_editor_dialog.xml | 40 +- BTLib/res/layout/window_layout.xml | 14 +- BTLib/res/values/strings.xml | 245 ++- 78 files changed, 918 insertions(+), 1983 deletions(-) diff --git a/BTLib/lint-baseline.xml b/BTLib/lint-baseline.xml index c159e5ef..a7d0eba6 100644 --- a/BTLib/lint-baseline.xml +++ b/BTLib/lint-baseline.xml @@ -4488,1315 +4488,6 @@ column="6"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_alignParentStart = "true"/> + android:layout_toEndOf="@id/lbl_label"/> @@ -69,7 +69,7 @@ android:layout_width = "225dp" android:layout_height = "wrap_content" android:singleLine = "true" - android:layout_toRightOf ="@id/flip_label_label" + android:layout_toEndOf ="@id/flip_label_label" android:layout_alignTop ="@id/flip_label_label"/> @@ -89,7 +89,7 @@ android:layout_width = "225dp" android:layout_height = "wrap_content" android:singleLine = "true" - android:layout_toRightOf ="@id/flip_label" + android:layout_toEndOf ="@id/flip_label" android:layout_alignTop ="@id/flip_label"/> @@ -132,9 +132,9 @@ android:text="Freeze"/> -