diff --git a/app/build.gradle b/app/build.gradle index d2980db..a9c8bcf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,7 @@ android { dependencies { + implementation 'com.humanware:KeySoftSDK:latest.release' //implementation 'androidx.core:core-ktx:1.7.0' //implementation 'androidx.appcompat:appcompat:1.6.0' diff --git a/app/src/main/java/ca/mcgill/a11y/image/BaseActivity.java b/app/src/main/java/ca/mcgill/a11y/image/BaseActivity.java index 54032e0..da5d57f 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/BaseActivity.java +++ b/app/src/main/java/ca/mcgill/a11y/image/BaseActivity.java @@ -62,6 +62,10 @@ import androidx.core.os.LocaleListCompat; import androidx.core.view.GestureDetectorCompat; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; +import com.humanware.keysoftsdk.ui.menu.AbstractMenuActivity; +import com.humanware.keysoftsdk.ui.menu.AccessibleListView; + import org.json.JSONException; import org.xml.sax.SAXException; @@ -78,11 +82,11 @@ import timber.log.Timber; // Base activity which is extended by all other activities. Implements functionality common to all/most activities -public class BaseActivity extends AppCompatActivity { - static BrailleDisplay brailleServiceObj = null; +public class BaseActivity extends AbstractMenuActivity { + private SelfBraillingManager brailleServiceObj = null; @SuppressLint("WrongConstant") @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); /*Configuration newConfig = new Configuration(); @@ -92,13 +96,14 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { AppCompatDelegate.setApplicationLocales(appLocale); // View Actions - setContentView(R.layout.activity_main); + //setContentView(R.layout.activity_main); if(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED){ checkPermission(); } if (DataAndMethods.brailleServiceObj==null) { - brailleServiceObj = (BrailleDisplay) getSystemService(BrailleDisplay.BRAILLE_DISPLAY_SERVICE); + brailleServiceObj = new SelfBraillingManager(this); + brailleServiceObj.bindService(); // TODO: You may need to put this in onResume instead. Usually we bind service in onResume but I'm unsure of the workflow of your app so I put it here for now. DataAndMethods.initialize(brailleServiceObj, getApplicationContext(), findViewById(android.R.id.content), getResources()); } else{ @@ -117,6 +122,17 @@ public void handleOnBackPressed() { this.getOnBackPressedDispatcher().addCallback(onBackPressedCallback);*/ } + + @Override + public int getTitleId() { + return R.string.app_name; + } + + @Override + public AccessibleListView.Sort initialize() { // TODO: Remove + return null; + } + // check permissions required for voice recognition private void checkPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -125,7 +141,9 @@ private void checkPermission() { } @Override - protected void onDestroy() { + public void onDestroy() { + brailleServiceObj.unbindService(); + brailleServiceObj = null; super.onDestroy(); } @@ -195,7 +213,7 @@ public boolean onTouchEvent(MotionEvent event) { } @Override - protected void onResume() { + public void onResume() { super.onResume(); } diff --git a/app/src/main/java/ca/mcgill/a11y/image/DataAndMethods.java b/app/src/main/java/ca/mcgill/a11y/image/DataAndMethods.java index 7da6916..e56b00b 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/DataAndMethods.java +++ b/app/src/main/java/ca/mcgill/a11y/image/DataAndMethods.java @@ -56,6 +56,9 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; +import com.humanware.keysoftsdk.selfbrailling.aidl.DotsMatrix; +import com.humanware.keysoftsdk.selfbrailling.widget.SelfBraillingWidget; import com.scand.svg.SVGHelper; import org.json.JSONArray; @@ -158,7 +161,7 @@ public class DataAndMethods { // showing/hiding non-target elements in guidance mode public static boolean showAll = false; - public static BrailleDisplay brailleServiceObj = null; + public static SelfBraillingManager brailleServiceObj = null; public static BrailleDisplay.MotionEventHandler handler; // keep track of current request to server private static Call ongoingCall; @@ -186,6 +189,7 @@ public class DataAndMethods { public static String tempImage = ""; public static String forceSpeak = null; public static Boolean silentStart = false; + public static byte[][] brailleScreen = null; // mapping of keyCodes public static Map keyMapping = new HashMap() {{ put(421, "UP"); @@ -207,65 +211,24 @@ public class DataAndMethods { public static Intent speechRecognizerIntent; public static Resources res; // initializes the Braille display, TTS and other common components in newly created activity - public static void initialize(BrailleDisplay brailleServiceObj, Context context, View view, Resources res) { + public static void initialize(SelfBraillingManager brailleServiceObj, Context context, View view, Resources res) { DataAndMethods.brailleServiceObj = brailleServiceObj; DataAndMethods.context = context; DataAndMethods.view = view; DataAndMethods.res = res; // sets array with dimensions of pin array to 0s; used to refresh the pins when required - data = new byte[brailleServiceObj.getDotLineCount()][]; + data = new byte[SelfBraillingWidget.MAXIMUM_HEIGHT][]; for (int i = 0; i < data.length; ++i) { - data[i] = new byte[brailleServiceObj.getDotPerLineCount()]; + data[i] = new byte[SelfBraillingWidget.MAXIMUM_WIDTH]; Arrays.fill(data[i], (byte) 0x00); } // empty string array to be populated with descriptions when the layer is loaded tags = new ArrayList<>(); - tags.add(new String[brailleServiceObj.getDotLineCount()][brailleServiceObj.getDotPerLineCount()]); - tags.add(new String[brailleServiceObj.getDotLineCount()][brailleServiceObj.getDotPerLineCount()]); + tags.add(new String[SelfBraillingWidget.MAXIMUM_HEIGHT][SelfBraillingWidget.MAXIMUM_WIDTH]); + tags.add(new String[SelfBraillingWidget.MAXIMUM_HEIGHT][SelfBraillingWidget.MAXIMUM_WIDTH]); - // only initialize tts if it is not already set up; otherwise this takes too long - if (tts == null) { - tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() { - - @Override - public void onInit(int status) { - - if (status != TextToSpeech.SUCCESS) { - Timber.e("error: "+ "Initialization Failed!" + status); - } else { - tts.setLanguage(Locale.forLanguageTag(res.getString(R.string.locale))); - tts.setOnUtteranceProgressListener(new UtteranceProgressListener() { - @Override - public void onStart(String s) { - if (s.equals("forceSpeak")) { - forceSpeak = null; - } - } - - @Override - public void onDone(String s) { - //Log.d("CHECKING!", s); - // plays ping when TTS readout is completed based on utteranceId - if (s.equals("ping")) { - pingsPlayer(R.raw.blip); - } - if (forceSpeak!= null){ - speaker(forceSpeak, TextToSpeech.QUEUE_FLUSH, "forceSpeak"); - //forceSpeak = null; - } - } - - @Override - public void onError(String s) { - - } - }); - } - } - }, "com.google.android.tts"); - } if (speechRecognizer == null) { // Voice Command Recognition Stuff speechRecognizer = SpeechRecognizer.createSpeechRecognizer(DataAndMethods.context); @@ -376,8 +339,14 @@ else if (history.type.equals("Map")) { } } + private static void displayDots(byte[][] matrix) { + brailleServiceObj.displayDots(new DotsMatrix(matrix)); + brailleScreen = matrix; + } + //check mode and display appropriate layer public static void displayGraphic(int keyCode, String mode, Boolean silentStart){ + Log.d("REFRESH", "displayGraphic!"); try{if (mode=="Exploration"){ DataAndMethods.ttsEnabled=true; @@ -387,8 +356,8 @@ public static void displayGraphic(int keyCode, String mode, Boolean silentStart) else{ -- DataAndMethods.presentLayer; } - brailleServiceObj.display(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), DataAndMethods.presentLayer, !silentStart)); - + displayDots(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), DataAndMethods.presentLayer, !silentStart)); + Log.d("REFRESH", "REFRESHING!"); } else if (mode=="Guidance"){ @@ -399,7 +368,8 @@ public static void displayGraphic(int keyCode, String mode, Boolean silentStart) else{ -- DataAndMethods.presentTarget; } - brailleServiceObj.display(DataAndMethods.getGuidanceBitmaps(DataAndMethods.getfreshDoc(), !silentStart)); + displayDots(DataAndMethods.getGuidanceBitmaps(DataAndMethods.getfreshDoc(), !silentStart)); + }} catch(IOException | SAXException | ParserConfigurationException | XPathExpressionException e) { Timber.e(e, "EXCEPTION"); @@ -543,9 +513,9 @@ public void run() { }); // reshape byte array into 2D array to match pin array dimensions - byte[][] dataRead = new byte[brailleServiceObj.getDotLineCount()][brailleServiceObj.getDotPerLineCount()]; + byte[][] dataRead = new byte[SelfBraillingWidget.MAXIMUM_HEIGHT][SelfBraillingWidget.MAXIMUM_WIDTH]; for (int i = 0; i < data.length; ++i) { - dataRead[i]= Arrays.copyOfRange(byteArray, i*brailleServiceObj.getDotPerLineCount(), (i+1)*brailleServiceObj.getDotPerLineCount()); + dataRead[i]= Arrays.copyOfRange(byteArray, i*SelfBraillingWidget.MAXIMUM_WIDTH, (i+1)*SelfBraillingWidget.MAXIMUM_WIDTH); } return dataRead; } @@ -608,9 +578,9 @@ else if (presentTarget > targetCount){ for (int i = 0; i < mask.length; i++) { byteArray[i] = (byte) (mask[i] * target[i]); } - byte[][] dataRead = new byte[brailleServiceObj.getDotLineCount()][brailleServiceObj.getDotPerLineCount()]; + byte[][] dataRead = new byte[SelfBraillingWidget.MAXIMUM_HEIGHT][SelfBraillingWidget.MAXIMUM_WIDTH]; for (int i = 0; i < data.length; ++i) { - dataRead[i]= Arrays.copyOfRange(byteArray, i*brailleServiceObj.getDotPerLineCount(), (i+1)*brailleServiceObj.getDotPerLineCount()); + dataRead[i]= Arrays.copyOfRange(byteArray, i*SelfBraillingWidget.MAXIMUM_WIDTH, (i+1)*SelfBraillingWidget.MAXIMUM_WIDTH); } return dataRead; @@ -623,9 +593,9 @@ public static void getDescriptions(Document doc) throws XPathExpressionException // query elements that are in the present layer AND have element level descriptions (NOT layer level descriptions) // Assuming that only elements with short description can have a long description here. Is this assumption safe?! NodeList nodeslist=(NodeList)xPath.evaluate("//*[not(ancestor-or-self::*[@display = 'none']) and not(descendant::*[@display = 'none']) and (not(self::*[@data-image-layer]) or not(child::*)) and ((self::*[@aria-labelledby] or self::*[@aria-label]) or parent::*[@data-image-layer])]", doc, XPathConstants.NODESET); // temporary var for objects tags - String[] layerTags=new String[brailleServiceObj.getDotPerLineCount()*brailleServiceObj.getDotLineCount()]; + String[] layerTags=new String[SelfBraillingWidget.MAXIMUM_WIDTH*SelfBraillingWidget.MAXIMUM_HEIGHT]; // temporary var for objects long descriptions - String[] layerDesc=new String[brailleServiceObj.getDotPerLineCount()*brailleServiceObj.getDotLineCount()]; + String[] layerDesc=new String[SelfBraillingWidget.MAXIMUM_WIDTH*SelfBraillingWidget.MAXIMUM_HEIGHT]; //Log.d("GETTING TAGS", String.valueOf(nodeslist.getLength())); // initially hiding all elements filtered in the previous stage for(int i = 0 ; i < nodeslist.getLength() ; i ++) { @@ -688,8 +658,8 @@ public static void getDescriptions(Document doc) throws XPathExpressionException // converting string array into 2D array that maps to the pins for (int i = 0; i < data.length; ++i) { - tags.get(0)[i]=Arrays.copyOfRange(layerTags, i*brailleServiceObj.getDotPerLineCount(), (i+1)*brailleServiceObj.getDotPerLineCount()); - tags.get(1)[i]=Arrays.copyOfRange(layerDesc, i*brailleServiceObj.getDotPerLineCount(), (i+1)*brailleServiceObj.getDotPerLineCount()); + tags.get(0)[i]=Arrays.copyOfRange(layerTags, i*SelfBraillingWidget.MAXIMUM_WIDTH, (i+1)*SelfBraillingWidget.MAXIMUM_WIDTH); + tags.get(1)[i]=Arrays.copyOfRange(layerDesc, i*SelfBraillingWidget.MAXIMUM_WIDTH, (i+1)*SelfBraillingWidget.MAXIMUM_WIDTH); } return; } @@ -699,13 +669,13 @@ public static byte[] docToBitmap(Document doc) throws IOException { String img= getStringFromDocument(doc).replace(" ", ""); //Log.d("SVG",img); //Log.d("DIMS", dims[0]+","+ dims[1]+","+dims[2]+","+dims[3]); - Bitmap svg = SVGHelper.noContext().open(img).setRequestBounds(brailleServiceObj.getDotPerLineCount(), brailleServiceObj.getDotLineCount()).getBitmap(); + Bitmap svg = SVGHelper.noContext().open(img).setRequestBounds(SelfBraillingWidget.MAXIMUM_WIDTH, SelfBraillingWidget.MAXIMUM_HEIGHT).getBitmap(); int x = svg.getWidth(); int y = svg.getHeight(); //Log.d("SVG",x+", "+ y); // padding bitmap to fit to pin array size - Bitmap svgScaled=padBitmap(svg, (brailleServiceObj.getDotPerLineCount()-x>0)?(brailleServiceObj.getDotPerLineCount()-x):0, - (brailleServiceObj.getDotLineCount()-y)>0?(brailleServiceObj.getDotLineCount()-y):0); + Bitmap svgScaled=padBitmap(svg, (SelfBraillingWidget.MAXIMUM_WIDTH-x>0)?(SelfBraillingWidget.MAXIMUM_WIDTH-x):0, + (SelfBraillingWidget.MAXIMUM_HEIGHT-y)>0?(SelfBraillingWidget.MAXIMUM_HEIGHT-y):0); svg.recycle(); // extracting only the alpha value of bitmap to convert it into a byte array Bitmap alphas=svgScaled.extractAlpha(); @@ -1118,20 +1088,20 @@ public static Document getfreshDoc() throws ParserConfigurationException, IOExce //Log.d("NEWDOC", width+", "+height); float x=0 ,y=0; float[] translations = new float[]{0 , 0}; - if (width/height > (float) brailleServiceObj.getDotPerLineCount()/ (float) brailleServiceObj.getDotLineCount()) { + if (width/height > (float) SelfBraillingWidget.MAXIMUM_WIDTH/ (float) SelfBraillingWidget.MAXIMUM_HEIGHT) { //padding along height x = width; - y = width * brailleServiceObj.getDotLineCount()/brailleServiceObj.getDotPerLineCount(); + y = width * SelfBraillingWidget.MAXIMUM_HEIGHT/SelfBraillingWidget.MAXIMUM_WIDTH; translations[1] = (y - height)/2; } else { //padding along width y = height; - x= height * brailleServiceObj.getDotPerLineCount()/brailleServiceObj.getDotLineCount(); + x= height * SelfBraillingWidget.MAXIMUM_WIDTH/SelfBraillingWidget.MAXIMUM_HEIGHT; translations[0] = (x- width)/2; } //Log.d("DIMS", width+ ", "+ height+ ";"+ x+ ", "+ y); - if((width/height- (float)brailleServiceObj.getDotPerLineCount()/ (float)brailleServiceObj.getDotLineCount())<0.01){ + if((width/height- (float)SelfBraillingWidget.MAXIMUM_WIDTH/ (float)SelfBraillingWidget.MAXIMUM_HEIGHT)<0.01){ node.setAttribute("width", String.valueOf(x)); node.setAttribute("height", String.valueOf(y)); NodeList nodeslist = (NodeList)xPath.evaluate("//*[self::*[@data-image-layer] and not(ancestor::metadata)]", doc, XPathConstants.NODESET); @@ -1185,8 +1155,8 @@ public static Integer[] pinCheck(float x, float y){ float yMax=1080; double epsilon= 0.000001; // Calculating pin based on position - int pinX= (int) (Math.ceil((x-xMin+epsilon)/((xMax-xMin)/brailleServiceObj.getDotPerLineCount()))-1); - int pinY= (int) Math.ceil((y-yMin+epsilon)/((yMax-yMin)/brailleServiceObj.getDotLineCount()))-1; + int pinX= (int) (Math.ceil((x-xMin+epsilon)/((xMax-xMin)/SelfBraillingWidget.MAXIMUM_WIDTH))-1); + int pinY= (int) Math.ceil((y-yMin+epsilon)/((yMax-yMin)/SelfBraillingWidget.MAXIMUM_HEIGHT))-1; return new Integer[] {pinX, pinY}; } @@ -1204,9 +1174,9 @@ public static void zoom(Integer[] pins, String mode) throws ParserConfigurationE zoomVal+= 25; node.setAttribute("viewBox", zoomer(width, height, zoomVal, pins)); if (mode.equals("Exploration")) - brailleServiceObj.display(getBitmaps(doc, presentLayer, false)); + displayDots(getBitmaps(doc, presentLayer, false)); else if (mode.equals("Guidance")) - brailleServiceObj.display(getGuidanceBitmaps(doc, false)); + displayDots(getGuidanceBitmaps(doc, false)); } else{ if (zoomVal <= 100){ @@ -1217,13 +1187,13 @@ else if (mode.equals("Guidance")) if (zoomVal < 100) zoomVal = 100; node.setAttribute("viewBox", zoomer(width, height, zoomVal, pins)); if (mode.equals("Exploration")) - brailleServiceObj.display(getBitmaps(doc, presentLayer, false)); + displayDots(getBitmaps(doc, presentLayer, false)); else if (mode.equals("Guidance")) { if (showAll){ - brailleServiceObj.display(DataAndMethods.displayTargetLayer(doc)); + displayDots(DataAndMethods.displayTargetLayer(doc)); } else { - brailleServiceObj.display(getGuidanceBitmaps(doc, false)); + displayDots(getGuidanceBitmaps(doc, false)); } } } @@ -1243,10 +1213,10 @@ public static String zoomer(float width, float height, int zoomVal, Integer[] pi //int bufferPins; - scalingFactor= brailleServiceObj.getDotPerLineCount()/widthNew; + scalingFactor= SelfBraillingWidget.MAXIMUM_WIDTH/widthNew; //Log.d("SCALE", String.valueOf(scalingFactor)); press[0] = (pins[0]/scalingFactor) + dims[0]; - scalingFactor = brailleServiceObj.getDotLineCount()/heightNew; + scalingFactor = SelfBraillingWidget.MAXIMUM_HEIGHT/heightNew; press[1] = (pins[1]/scalingFactor) + dims[1]; //Log.d("PINS", pins[0]+", "+pins[1]); @@ -1256,10 +1226,10 @@ public static String zoomer(float width, float height, int zoomVal, Integer[] pi //Log.d("SCALE", zoomWidth+","+zoomHeight); // zoom while keeping the portion of the image at the point of press at the same pins post zoom - scalingFactor = zoomWidth/brailleServiceObj.getDotPerLineCount(); + scalingFactor = zoomWidth/SelfBraillingWidget.MAXIMUM_WIDTH; dims[0] = press[0] - (scalingFactor * (pins[0])); dims[2] = dims[0] + zoomWidth; - scalingFactor = zoomHeight / brailleServiceObj.getDotLineCount(); + scalingFactor = zoomHeight / SelfBraillingWidget.MAXIMUM_HEIGHT; dims [1] = press[1] - (scalingFactor * (pins[1])); dims[3] = dims[1] + zoomHeight; //Log.d("NEW DIMS", dims[0]+","+dims[1]+","+dims[2]+","+dims[3]); @@ -1351,20 +1321,20 @@ else if (dims[3]>(height+origDims[1])){ node.setAttribute("viewBox", zoomBox); //Log.d("PAN", zoomBox); if (className.equals("renderers.Exploration") || className.equals("renderers.BasicPhotoMapRenderer")) - brailleServiceObj.display(getBitmaps(doc, presentLayer, false)); + displayDots(getBitmaps(doc, presentLayer, false)); if (className.equals("renderers.Guidance")){ if (showAll){ - brailleServiceObj.display(DataAndMethods.displayTargetLayer(doc)); + displayDots(DataAndMethods.displayTargetLayer(doc)); } else { - brailleServiceObj.display(getGuidanceBitmaps(doc, false)); + displayDots(getGuidanceBitmaps(doc, false)); } } } // TTS speaker. Probably needs a little more work on flushing and/or selecting whether to continue playing public static void speaker(String text, int queue, String... utterId){ - tts.speak (text, queue, null, utterId.length > 0 ? utterId[0] : "000000"); + brailleServiceObj.announceText(text); // TODO: QUEUE MODE IS FORCED TO QUEUE_INTERRUPT in announceText method. We (Humanware) will need to add functionality to select queue mode in future SDK version. return; } @@ -1407,9 +1377,9 @@ public void run() { } }); - byte[][] dataRead = new byte[brailleServiceObj.getDotLineCount()][brailleServiceObj.getDotPerLineCount()]; + byte[][] dataRead = new byte[SelfBraillingWidget.MAXIMUM_HEIGHT][SelfBraillingWidget.MAXIMUM_WIDTH]; for (int i = 0; i < data.length; ++i) { - dataRead[i]= Arrays.copyOfRange(byteArray, i*brailleServiceObj.getDotPerLineCount(), (i+1)*brailleServiceObj.getDotPerLineCount()); + dataRead[i]= Arrays.copyOfRange(byteArray, i*SelfBraillingWidget.MAXIMUM_WIDTH, (i+1)*SelfBraillingWidget.MAXIMUM_WIDTH); } return dataRead; } @@ -1426,15 +1396,15 @@ public static boolean validateRegion(Integer[] region){ // show ROI selected public static void showRegion(Integer[] region) throws XPathExpressionException, ParserConfigurationException, IOException, SAXException { byte[][] data = DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), DataAndMethods.presentLayer, false); - byte[][] selection = new byte[brailleServiceObj.getDotLineCount()][]; + byte[][] selection = new byte[SelfBraillingWidget.MAXIMUM_HEIGHT][]; //Log.d("DATA", String.valueOf(data[0].length)); for (int i = 0; i < selection.length; ++i) { - selection[i] = new byte[brailleServiceObj.getDotPerLineCount()]; + selection[i] = new byte[SelfBraillingWidget.MAXIMUM_WIDTH]; if (i>=region[1] && i<=region[3]) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream( ); outputStream.write( Arrays.copyOfRange(DataAndMethods.data[i], 0 ,region[0] )); outputStream.write( Arrays.copyOfRange(data[i], region[0] ,region[2]+1 ) ); - outputStream.write( Arrays.copyOfRange(DataAndMethods.data[i], region[2]+1 ,brailleServiceObj.getDotPerLineCount() )); + outputStream.write( Arrays.copyOfRange(DataAndMethods.data[i], region[2]+1 ,SelfBraillingWidget.MAXIMUM_WIDTH )); selection[i]= outputStream.toByteArray( ); } else{ @@ -1442,7 +1412,7 @@ public static void showRegion(Integer[] region) throws XPathExpressionException, Arrays.fill(selection[i], (byte) 0x00); } } - brailleServiceObj.display(selection); + displayDots(selection); } // make follow up query to server public static void sendFollowUpQuery(String query, Integer[] region) throws JSONException, IOException { @@ -1455,8 +1425,8 @@ public static void sendFollowUpQuery(String query, Integer[] region) throws JSON if (region!=null){ focus= new Float[]{0f, 0f, 0f, 0f}; Float[] currentDims = Arrays.stream(zoomBox.split(" ", -1)).map(Float::valueOf).toArray(Float[]::new); - Float xPerDot = currentDims[2]/ DataAndMethods.brailleServiceObj.getDotPerLineCount(); - Float yPerDot = currentDims[3]/ DataAndMethods.brailleServiceObj.getDotLineCount(); + Float xPerDot = currentDims[2]/ SelfBraillingWidget.MAXIMUM_WIDTH; + Float yPerDot = currentDims[3]/ SelfBraillingWidget.MAXIMUM_HEIGHT; Float xShift = origRatioDims[0]==0f?0f:(origDims[2]-origRatioDims[0])/2; Float yShift = origRatioDims[1]==0f?0f:(origDims[3]-origRatioDims[1])/2; diff --git a/app/src/main/java/ca/mcgill/a11y/image/FollowUpQuery.java b/app/src/main/java/ca/mcgill/a11y/image/FollowUpQuery.java index 4633f90..8d4ed1e 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/FollowUpQuery.java +++ b/app/src/main/java/ca/mcgill/a11y/image/FollowUpQuery.java @@ -35,6 +35,9 @@ import android.view.KeyEvent; import android.view.MotionEvent; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; +import com.humanware.keysoftsdk.selfbrailling.widget.SelfBraillingWidget; + import org.json.JSONException; import org.xml.sax.SAXException; @@ -54,9 +57,11 @@ public class FollowUpQuery extends BaseActivity implements GestureDetector.OnGes Integer[] region = null; private GestureDetectorCompat mDetector; - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; + private SelfBraillingWidget widget = null; + @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Timber.d("ACTIVITY: "+ "FollowUpQuery Created"); super.onCreate(savedInstanceState); brailleServiceObj = DataAndMethods.brailleServiceObj; @@ -69,7 +74,7 @@ public void updateState() { case 0: // Log.d("QUERY", query); try { - brailleServiceObj.display(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), DataAndMethods.presentLayer, false)); + brailleServiceObj.displayDots(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), DataAndMethods.presentLayer, false)); } catch (IOException | XPathExpressionException | ParserConfigurationException | SAXException e) { Timber.e(e, "EXCEPTION"); @@ -275,7 +280,7 @@ public boolean onSingleTapConfirmed(MotionEvent event) { } @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "FollowUpQuery Resumed"); intent = getIntent(); query = intent.getStringExtra("query"); @@ -293,17 +298,19 @@ protected void onResume() { return false; }; - brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); + widget = new SelfBraillingWidget(this); + setContentView(widget); + //brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); state = -1; updateState(); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "FollowUpQuery Paused"); DataAndMethods.presentLayer--; - brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); super.onPause(); } } \ No newline at end of file diff --git a/app/src/main/java/ca/mcgill/a11y/image/ShowFollowUp.java b/app/src/main/java/ca/mcgill/a11y/image/ShowFollowUp.java index dfd1d55..b4dc99d 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/ShowFollowUp.java +++ b/app/src/main/java/ca/mcgill/a11y/image/ShowFollowUp.java @@ -34,6 +34,8 @@ import androidx.core.view.GestureDetectorCompat; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; + import org.json.JSONException; import org.xml.sax.SAXException; @@ -49,9 +51,9 @@ public class ShowFollowUp extends BaseActivity implements GestureDetector.OnGest Intent intent; String mainGraphic; private GestureDetectorCompat mDetector; - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Timber.d("ACTIVITY: "+ "FollowUpQuery Created"); super.onCreate(savedInstanceState); brailleServiceObj = DataAndMethods.brailleServiceObj; @@ -180,12 +182,12 @@ public boolean onSingleTapConfirmed(MotionEvent event) { } @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "FollowUpQuery Resumed"); intent = getIntent(); mainGraphic = intent.getStringExtra("image"); try { - brailleServiceObj.display(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), 0, true)); + brailleServiceObj.displayDots(DataAndMethods.getBitmaps(DataAndMethods.getfreshDoc(), 0, true)); } catch (IOException | XPathExpressionException | ParserConfigurationException | SAXException e) { Timber.e(e, "EXCEPTION"); throw new RuntimeException(e); @@ -203,11 +205,11 @@ protected void onResume() { return false; }; - brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "FollowUpQuery Paused"); DataAndMethods.image = mainGraphic; resetGraphicParams(); @@ -220,7 +222,7 @@ protected void onPause() { DataAndMethods.tempImage = ""; DataAndMethods.followup = false; DataAndMethods.presentLayer--; - brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); super.onPause(); } } \ No newline at end of file diff --git a/app/src/main/java/ca/mcgill/a11y/image/renderers/BasicPhotoMapRenderer.java b/app/src/main/java/ca/mcgill/a11y/image/renderers/BasicPhotoMapRenderer.java index 4fa786e..007536d 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/renderers/BasicPhotoMapRenderer.java +++ b/app/src/main/java/ca/mcgill/a11y/image/renderers/BasicPhotoMapRenderer.java @@ -34,6 +34,9 @@ import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; + +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; + import org.xml.sax.SAXException; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -49,12 +52,12 @@ // renders graphic currently stored in string 'image' public class BasicPhotoMapRenderer extends BaseActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MediaPlayer.OnCompletionListener { - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; private GestureDetectorCompat mDetector; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_basic_photo_renderer); brailleServiceObj = DataAndMethods.brailleServiceObj; @@ -204,7 +207,7 @@ public boolean onSingleTapConfirmed(MotionEvent event) { } @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "Exploration Resumed"); DataAndMethods.displayGraphic(DataAndMethods.confirmButton, "Exploration", silentStart); @@ -224,13 +227,13 @@ protected void onResume() { return false; }; - brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "BasicPhotoMapRenderer Paused"); - brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); super.onPause(); } } \ No newline at end of file diff --git a/app/src/main/java/ca/mcgill/a11y/image/renderers/Exploration.java b/app/src/main/java/ca/mcgill/a11y/image/renderers/Exploration.java index 5c7f86a..e4ba020 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/renderers/Exploration.java +++ b/app/src/main/java/ca/mcgill/a11y/image/renderers/Exploration.java @@ -23,21 +23,19 @@ //import static ca.mcgill.a11y.image.DataAndMethods.followingUp; import static ca.mcgill.a11y.image.DataAndMethods.keyMapping; import static ca.mcgill.a11y.image.DataAndMethods.silentStart; -import static ca.mcgill.a11y.image.DataAndMethods.update; import android.annotation.SuppressLint; -import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; -import android.os.BrailleDisplay; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.util.Log; +import android.util.Size; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; -import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity; import androidx.core.view.GestureDetectorCompat; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; @@ -50,36 +48,90 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; -import androidx.lifecycle.MutableLiveData; -import ca.mcgill.a11y.image.BaseActivity; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; +import com.humanware.keysoftsdk.selfbrailling.aidl.DotsMatrix; +import com.humanware.keysoftsdk.selfbrailling.widget.SelfBraillingWidget; + import ca.mcgill.a11y.image.DataAndMethods; import ca.mcgill.a11y.image.PollingService; import ca.mcgill.a11y.image.R; import timber.log.Timber; -public class Exploration extends BaseActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MediaPlayer.OnCompletionListener { - private BrailleDisplay brailleServiceObj = null; +public class Exploration extends AppCompatActivity { private GestureDetectorCompat mDetector; + private SelfBraillingWidget braillingWidget = null; + private MutableLiveData mutableViewedImage = new MutableLiveData<>(); @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { - Intent intent = getIntent(); + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + braillingWidget = new SelfBraillingWidget(this); + //braillingWidget.updateDimensionsFromBrailleDisplay(DataAndMethods.brailleServiceObj.getBrailleDisplayDotsSizeX(), DataAndMethods.brailleServiceObj.getBrailleDisplayDotsSizeY()); + setContentView(braillingWidget); + if (getSupportActionBar() != null) { // makes widget full screen by hiding action bar + getSupportActionBar().hide(); + } + braillingWidget.setOnSelfBraillingWidgetListener(new SelfBraillingWidget.OnSelfBraillingWidgetListener() { + @Override + public void onFocused() { + + } + + @Override + public void onDoubleTapAtBraillePosition(int pointX, int pointY) { + Log.d("POINT", pointX + ", " + pointY); + ArrayList tags = DataAndMethods.tags; + Integer [] pins=DataAndMethods.pinCheck(pointX, pointY); + try{ + // Check if zooming mode is enabled + if (DataAndMethods.zoomingIn || DataAndMethods.zoomingOut) { + DataAndMethods.zoom(pins, "Exploration"); + } + else { + // Log.d("TAGS", "ACCESS TTS"); + // Speak out label tags based on finger location and ping when detailed description is available + if ((tags.get(1)[pins[1]][pins[0]] != null) && (tags.get(1)[pins[1]][pins[0]].trim().length() > 0)) { + //Log.d("CHECKING!", tags.get(1)[pins[1]][pins[0]]); + DataAndMethods.speaker(tags.get(0)[pins[1]][pins[0]], TextToSpeech.QUEUE_FLUSH, "ping"); + } else { + //Log.d("CHECKING!", tags.get(0)[pins[1]][pins[0]]); + DataAndMethods.speaker(tags.get(0)[pins[1]][pins[0]], TextToSpeech.QUEUE_FLUSH); + } + } + } + catch(RuntimeException ex){ + Timber.e(ex, "TTS ERROR"); + } catch (XPathExpressionException | ParserConfigurationException | IOException | SAXException e) { + Timber.e(e, "EXCEPTION"); + throw new RuntimeException(e); + } + } + + @Override + public void onSingleTapAtBraillePosition(int i, int i1) { + return; + } + }); + + mutableViewedImage.observe(this, it -> braillingWidget.refresh(it)); + //mutableLiveDots.observe(this, it -> DataAndMethods.brailleServiceObj.displayDots(new DotsMatrix(it))); //setContentView(R.layout.activity_main); //mDetector = new GestureDetectorCompat(getApplicationContext(),this); // Set the gesture detector as the double tap //mDetector.setOnDoubleTapListener(this); - brailleServiceObj = DataAndMethods.brailleServiceObj; // DataAndMethods.initialize(brailleServiceObj, getApplicationContext(), findViewById(android.R.id.content)); DataAndMethods.image = null; DataAndMethods.update.observe(this,new Observer() { @Override public void onChanged(Boolean changedVal) { if (changedVal && DataAndMethods.image != null){ + Log.d("UPDATE!", "Updating image in Exploration"); displayGraphic(confirmButton, "Exploration", silentStart); + mutableViewedImage.setValue(DataAndMethods.brailleScreen); if (silentStart) silentStart = false; } @@ -102,6 +154,7 @@ public void onChanged(Boolean changedVal) { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { super.onKeyDown(keyCode, event); + Log.d("KEY EVENT", keyMapping.getOrDefault(keyCode, "default")); switch (keyMapping.getOrDefault(keyCode, "default")) { // Navigating between files case "UP": @@ -130,62 +183,15 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { DataAndMethods.pingsPlayer(R.raw.blip); DataAndMethods.speechRecognizer.startListening(DataAndMethods.speechRecognizerIntent); return true; + case "BACK": + super.onBackPressed(); + return true; default: Timber.d("KEY EVENT: "+ event.toString()); return false; } } - @Override - public boolean onTouchEvent(MotionEvent event){ - if (this.mDetector.onTouchEvent(event)) { - int action = event.getActionMasked(); - if (action==MotionEvent.ACTION_UP) - { - ArrayList tags = DataAndMethods.tags; - Integer [] pins=DataAndMethods.pinCheck(event.getX(), event.getY()); - try{ - // Check if zooming mode is enabled - if (DataAndMethods.zoomingIn || DataAndMethods.zoomingOut){ - DataAndMethods.zoom(pins, "Exploration"); - } - else { - // Log.d("TAGS", "ACCESS TTS"); - // Speak out label tags based on finger location and ping when detailed description is available - if ((tags.get(1)[pins[1]][pins[0]] != null) && (tags.get(1)[pins[1]][pins[0]].trim().length() > 0)) { - //Log.d("CHECKING!", tags.get(1)[pins[1]][pins[0]]); - DataAndMethods.speaker(tags.get(0)[pins[1]][pins[0]], TextToSpeech.QUEUE_FLUSH, "ping"); - } else { - //Log.d("CHECKING!", tags.get(0)[pins[1]][pins[0]]); - DataAndMethods.speaker(tags.get(0)[pins[1]][pins[0]], TextToSpeech.QUEUE_FLUSH); - } - } - } - catch(RuntimeException ex){ - Timber.e(ex, "TTS ERROR"); - } catch (XPathExpressionException | ParserConfigurationException | IOException | SAXException e) { - Timber.e(e, "EXCEPTION"); - throw new RuntimeException(e); - } - } - } - return true; - } - - @Override - public boolean onDown(MotionEvent event) { - // Log.d("GESTURE!","onDown: " + event.toString()); - - return true; - } - - @Override - public boolean onFling(MotionEvent event1, MotionEvent event2, - float velocityX, float velocityY) { - // Log.d("GESTURE!", "onFling: " + event1.toString() + event2.toString()); - return true; - } - @Override public void onLongPress(MotionEvent event) { Integer [] pins= DataAndMethods.pinCheck(event.getX(), event.getY()); try{ @@ -200,48 +206,7 @@ public void onLongPress(MotionEvent event) { } @Override - public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, - float distanceY) { - // Log.d("GESTURE!", "onScroll: " + event1.toString() + event2.toString()); - return true; - } - - @Override - public void onShowPress(MotionEvent event) { - // Log.d("GESTURE!", "onShowPress: " + event.toString()); - } - - @Override - public boolean onSingleTapUp(MotionEvent event) { - // Log.d("GESTURE!", "onSingleTapUp: " + event.toString()); - return true; - } - - @Override - public boolean onDoubleTap(MotionEvent event) { - // Log.d("GESTURE!", "onDoubleTap: " + event.toString()); - return true; - } - - @Override - public boolean onDoubleTapEvent(MotionEvent event) { - // Log.d("GESTURE!", "onDoubleTapEvent: " + event.toString()); - return true; - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent event) { - // Log.d("GESTURE!", "onSingleTapConfirmed: " + event.toString()); - return true; - } - - @Override - public void onCompletion(MediaPlayer mediaPlayer) { - mediaPlayer.release(); - } - - @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "Exploration Resumed"); if (!silentStart) DataAndMethods.speaker(getString(R.string.exploration_mode), TextToSpeech.QUEUE_FLUSH); @@ -249,28 +214,14 @@ protected void onResume() { //if (!followingUp.getValue()) { startService(new Intent(getApplicationContext(), PollingService.class)); //} - mDetector = new GestureDetectorCompat(this,this); - mDetector.setOnDoubleTapListener(this); - - DataAndMethods.handler = e -> { - if(DataAndMethods.ttsEnabled){ - try{ - onTouchEvent(e); - } - catch(RuntimeException ex){ - Timber.e(ex, "EXCEPTION"); - }} - - return false; - }; - brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "Exploration Paused"); stopService(new Intent(getApplicationContext(), PollingService.class)); - brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); super.onPause(); } diff --git a/app/src/main/java/ca/mcgill/a11y/image/renderers/Guidance.java b/app/src/main/java/ca/mcgill/a11y/image/renderers/Guidance.java index 250bbda..9b5f707 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/renderers/Guidance.java +++ b/app/src/main/java/ca/mcgill/a11y/image/renderers/Guidance.java @@ -36,6 +36,8 @@ import androidx.core.view.GestureDetectorCompat; import androidx.lifecycle.Observer; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; + import org.json.JSONException; import org.xml.sax.SAXException; @@ -53,12 +55,12 @@ import timber.log.Timber; public class Guidance extends BaseActivity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, MediaPlayer.OnCompletionListener { - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; private GestureDetectorCompat mDetector; @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); @@ -201,9 +203,9 @@ public boolean onDoubleTap(MotionEvent event) { // Log.d("GESTURE!", "onDoubleTap: " + event.toString()); try { if (!DataAndMethods.showAll) - brailleServiceObj.display(DataAndMethods.displayTargetLayer(DataAndMethods.getfreshDoc())); + brailleServiceObj.displayDots(DataAndMethods.displayTargetLayer(DataAndMethods.getfreshDoc())); else { - brailleServiceObj.display(DataAndMethods.getGuidanceBitmaps(DataAndMethods.getfreshDoc(), true)); + brailleServiceObj.displayDots(DataAndMethods.getGuidanceBitmaps(DataAndMethods.getfreshDoc(), true)); DataAndMethods.showAll = !DataAndMethods.showAll; } //DataAndMethods.showAll = !DataAndMethods.showAll; @@ -233,7 +235,7 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "Guidance Resumed"); DataAndMethods.speaker(getString(R.string.guidance_mode), TextToSpeech.QUEUE_FLUSH); startService(new Intent(getApplicationContext(), PollingService.class)); @@ -251,14 +253,14 @@ protected void onResume() { return false; }; - brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.registerMotionEventHandler(DataAndMethods.handler); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "Guidance Paused"); stopService(new Intent(getApplicationContext(), PollingService.class)); - brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); + //brailleServiceObj.unregisterMotionEventHandler(DataAndMethods.handler); super.onPause(); } diff --git a/app/src/main/java/ca/mcgill/a11y/image/selectors/ClassroomSelector.java b/app/src/main/java/ca/mcgill/a11y/image/selectors/ClassroomSelector.java index dbe00a5..fb7d654 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/selectors/ClassroomSelector.java +++ b/app/src/main/java/ca/mcgill/a11y/image/selectors/ClassroomSelector.java @@ -51,6 +51,10 @@ import javax.xml.xpath.XPathExpressionException; import androidx.lifecycle.MutableLiveData; +import com.humanware.keysoftsdk.ui.menu.AccessibleListView; +import com.humanware.keysoftsdk.ui.menu.accessibleitem.AccessibleItem; +import com.humanware.keysoftsdk.ui.menu.accessibleitem.attributes.AccessibleItemAttributes; + import ca.mcgill.a11y.image.BaseActivity; import ca.mcgill.a11y.image.DataAndMethods; import ca.mcgill.a11y.image.PollingService; @@ -64,55 +68,62 @@ public class ClassroomSelector extends BaseActivity implements MediaPlayer.OnCom @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_classroom_selector); + //setContentView(R.layout.activity_classroom_selector); channelSubscribed = getApplicationContext().getString(R.string.share_code); // DataAndMethods.initialize(brailleServiceObj, getApplicationContext(), findViewById(android.R.id.content)); + } - ((Button) findViewById(R.id.exploration_mode)).setOnKeyListener(btnListener); - ((Button) findViewById(R.id.exploration_mode)).setOnFocusChangeListener(focusListener); - ((Button) findViewById(R.id.guidance_mode)).setOnKeyListener(btnListener); - ((Button) findViewById(R.id.guidance_mode)).setOnFocusChangeListener(focusListener); + @Override + public AccessibleListView.Sort initialize() { + listview = inflateSettingItemLayout(); + return AccessibleListView.Sort.BY_POSITION; } + private AccessibleListView inflateSettingItemLayout() { + AccessibleListView listView = findViewById(com.humanware.keysoftsdk.R.id.settings_listview); + listView.setNext(makeAccessibleItem(R.string.exploration_mode)); + listView.setNext(makeAccessibleItem(R.string.guidance_mode)); - private View.OnFocusChangeListener focusListener = new View.OnFocusChangeListener(){ - @Override - public void onFocusChange(View view, boolean b) { - switch (view.getId()){ - case R.id.exploration_mode: - speaker(getResources().getString(R.string.exploration_mode), TextToSpeech.QUEUE_FLUSH); + listView.setOnItemClickListener((parent, view, position, id) -> { + Class targetActivity; + + switch (position) { + case 0: + targetActivity = Exploration.class; + //DataAndMethods.speaker(getResources().getString(R.string.swi_exploration_mode), TextToSpeech.QUEUE_FLUSH); break; - case R.id.guidance_mode: - speaker(getResources().getString(R.string.guidance_mode), TextToSpeech.QUEUE_FLUSH); + case 1: + targetActivity = Guidance.class; + //DataAndMethods.speaker(getResources().getString(R.string.swi_guidance_mode), TextToSpeech.QUEUE_FLUSH); break; + default: + throw new UnsupportedOperationException(); } - } - }; - private View.OnKeyListener btnListener = new View.OnKeyListener() { - @Override - public boolean onKey(View view, int i, KeyEvent keyEvent) { - if (keyEvent.getKeyCode()== DataAndMethods.confirmButton && - keyEvent.getAction()== KeyEvent.ACTION_DOWN){ - Intent myIntent = null; - if ((findViewById(R.id.exploration_mode)).hasFocus()){ - myIntent = new Intent(getApplicationContext(), Exploration.class); - DataAndMethods.speaker(getResources().getString(R.string.swi_exploration_mode), TextToSpeech.QUEUE_FLUSH); - } - else if ((findViewById(R.id.guidance_mode)).hasFocus()){ - myIntent = new Intent(getApplicationContext(), Guidance.class); - DataAndMethods.speaker(getResources().getString(R.string.swi_guidance_mode), TextToSpeech.QUEUE_FLUSH); - } - //Code snippet 3 - myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - getApplicationContext().startActivity(myIntent); - } - return false; - }}; + Intent myIntent = new Intent(this, targetActivity); + //Code snippet 3 + myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(myIntent); + }); + + return listView; + } + + private AccessibleItem makeAccessibleItem( + int labelNameId + ) { + return new AccessibleItem( + new AccessibleItemAttributes( + getResources().getString(labelNameId), + com.humanware.keysoftsdk.R.layout.one_textview, + com.humanware.keysoftsdk.R.id.textview + ) + ); + } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { @@ -149,14 +160,14 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "Classroom Selector Resumed"); - DataAndMethods.speaker(getResources().getString(R.string.res_classroom_selector), TextToSpeech.QUEUE_FLUSH); + //DataAndMethods.speaker(getResources().getString(R.string.res_classroom_selector), TextToSpeech.QUEUE_FLUSH); //startService(new Intent(getApplicationContext(), PollingService.class)); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "Exploration Paused"); //stopService(new Intent(getApplicationContext(), PollingService.class)); super.onPause(); diff --git a/app/src/main/java/ca/mcgill/a11y/image/selectors/MapSelector.java b/app/src/main/java/ca/mcgill/a11y/image/selectors/MapSelector.java index 55a1a2f..f8aa99d 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/selectors/MapSelector.java +++ b/app/src/main/java/ca/mcgill/a11y/image/selectors/MapSelector.java @@ -31,6 +31,8 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.Observer; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; + import org.json.JSONException; import ca.mcgill.a11y.image.renderers.BasicPhotoMapRenderer; @@ -40,12 +42,12 @@ // generates map request using latitude and longitude coordinates and allows for selecting among map renderer(s) public class MapSelector extends AppCompatActivity implements MediaPlayer.OnCompletionListener{ - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); super.onCreate(savedInstanceState); setContentView(R.layout.activity_map_selector); @@ -106,14 +108,14 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+"MapSelector Resumed"); DataAndMethods.speaker(getResources().getString(R.string.res_map_selector), TextToSpeech.QUEUE_FLUSH); DataAndMethods.image= null; super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "MapSelector Paused"); super.onPause(); } diff --git a/app/src/main/java/ca/mcgill/a11y/image/selectors/ModeSelector.java b/app/src/main/java/ca/mcgill/a11y/image/selectors/ModeSelector.java index 78ca6e4..f0a8a79 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/selectors/ModeSelector.java +++ b/app/src/main/java/ca/mcgill/a11y/image/selectors/ModeSelector.java @@ -23,10 +23,8 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.media.MediaPlayer; -import android.os.BrailleDisplay; import android.os.Bundle; import android.speech.tts.TextToSpeech; -import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -36,84 +34,66 @@ import androidx.core.os.LocaleListCompat; import androidx.core.view.GestureDetectorCompat; -import java.util.Locale; +import com.humanware.keysoftsdk.selfbrailling.SelfBraillingManager; +import com.humanware.keysoftsdk.ui.menu.AccessibleListView; +import com.humanware.keysoftsdk.ui.menu.accessibleitem.AccessibleItem; +import com.humanware.keysoftsdk.ui.menu.accessibleitem.attributes.AccessibleItemAttributes; import ca.mcgill.a11y.image.BaseActivity; import ca.mcgill.a11y.image.DataAndMethods; -import ca.mcgill.a11y.image.renderers.Exploration; import ca.mcgill.a11y.image.R; import timber.log.Timber; // Launcher activity; switches mode of application public class ModeSelector extends BaseActivity implements MediaPlayer.OnCompletionListener { - private BrailleDisplay brailleServiceObj = null; - private GestureDetectorCompat mDetector; - - @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_mode_selector); - - brailleServiceObj = DataAndMethods.brailleServiceObj; - // DataAndMethods.initialize(brailleServiceObj, getApplicationContext(), findViewById(android.R.id.content)); - - ((Button) findViewById(R.id.classroom_mode)).setOnKeyListener(btnListener); - ((Button) findViewById(R.id.classroom_mode)).setOnFocusChangeListener(focusListener); - ((Button) findViewById(R.id.photo_mode)).setOnKeyListener(btnListener); - ((Button) findViewById(R.id.photo_mode)).setOnFocusChangeListener(focusListener); - ((Button) findViewById(R.id.map_mode)).setOnKeyListener(btnListener); - ((Button) findViewById(R.id.map_mode)).setOnFocusChangeListener(focusListener); - // Code snippet 1 - + public AccessibleListView.Sort initialize() { + listview = inflateSettingItemLayout(); + return AccessibleListView.Sort.BY_POSITION; } - private View.OnFocusChangeListener focusListener = new View.OnFocusChangeListener(){ - @Override - public void onFocusChange(View view, boolean b) { - switch (view.getId()){ - case R.id.classroom_mode: - speaker(getResources().getString(R.string.classroom_mode),TextToSpeech.QUEUE_FLUSH); + private AccessibleListView inflateSettingItemLayout() { + AccessibleListView listView = findViewById(com.humanware.keysoftsdk.R.id.settings_listview); + listView.setNext(makeAccessibleItem(R.string.classroom_mode)); + listView.setNext(makeAccessibleItem(R.string.photo_mode)); + listView.setNext(makeAccessibleItem(R.string.map_mode)); + + listView.setOnItemClickListener((parent, view, position, id) -> { + Class targetActivity; + switch (position) { + case 0: + targetActivity = ClassroomSelector.class; + //DataAndMethods.speaker(getResources().getString(R.string.swi_classroom_mode), TextToSpeech.QUEUE_FLUSH); break; - case R.id.photo_mode: - speaker(getResources().getString(R.string.photo_mode), TextToSpeech.QUEUE_FLUSH); + case 1: + targetActivity = PhotoSelector.class; + //DataAndMethods.speaker(getResources().getString(R.string.swi_photo_mode), TextToSpeech.QUEUE_FLUSH); break; - case R.id.map_mode: - speaker(getResources().getString(R.string.map_mode), TextToSpeech.QUEUE_FLUSH); + case 2: + targetActivity = MapSelector.class; + //DataAndMethods.speaker(getResources().getString(R.string.swi_map_mode), TextToSpeech.QUEUE_FLUSH); break; - // Code snippet 2 - } - } - }; - private View.OnKeyListener btnListener = new View.OnKeyListener() { - @Override - public boolean onKey(View view, int i, KeyEvent keyEvent) { - if (keyEvent.getKeyCode()== DataAndMethods.confirmButton && - keyEvent.getAction()== KeyEvent.ACTION_DOWN){ - Intent myIntent = null; - if ((findViewById(R.id.classroom_mode)).hasFocus()){ - myIntent = new Intent(getApplicationContext(), ClassroomSelector.class); - DataAndMethods.speaker(getResources().getString(R.string.swi_classroom_mode), TextToSpeech.QUEUE_FLUSH); - } - else if ((findViewById(R.id.photo_mode)).hasFocus()){ - myIntent = new Intent(getApplicationContext(), PhotoSelector.class); - DataAndMethods.speaker(getResources().getString(R.string.swi_photo_mode), TextToSpeech.QUEUE_FLUSH); - - } - else if ((findViewById(R.id.map_mode)).hasFocus()){ - myIntent = new Intent(getApplicationContext(), MapSelector.class); - DataAndMethods.speaker(getResources().getString(R.string.swi_map_mode), TextToSpeech.QUEUE_FLUSH); - } - //Code snippet 3 - myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - getApplicationContext().startActivity(myIntent); + default: + throw new UnsupportedOperationException(); } - return false; - }}; - + startActivity(new Intent(this, targetActivity)); + }); + return listView; + } + private AccessibleItem makeAccessibleItem( + int labelNameId + ) { + return new AccessibleItem( + new AccessibleItemAttributes( + getResources().getString(labelNameId), + com.humanware.keysoftsdk.R.layout.one_textview, + com.humanware.keysoftsdk.R.id.textview + ) + ); + } @Override public boolean onTouchEvent(MotionEvent event){ @@ -127,15 +107,15 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Timber.d("ACTIVITY: "+ "ModeSelector Resumed"); - DataAndMethods.speaker(getResources().getString(R.string.res_mode_selector), TextToSpeech.QUEUE_FLUSH); + //DataAndMethods.speaker(getResources().getString(R.string.res_mode_selector), TextToSpeech.QUEUE_FLUSH); DataAndMethods.image = null; update.setValue(false); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "ModeSelector Paused"); super.onPause(); } diff --git a/app/src/main/java/ca/mcgill/a11y/image/selectors/PhotoSelector.java b/app/src/main/java/ca/mcgill/a11y/image/selectors/PhotoSelector.java index 808b25b..7a2cb16 100644 --- a/app/src/main/java/ca/mcgill/a11y/image/selectors/PhotoSelector.java +++ b/app/src/main/java/ca/mcgill/a11y/image/selectors/PhotoSelector.java @@ -43,7 +43,7 @@ public class PhotoSelector extends BaseActivity implements MediaPlayer.OnComplet @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); super.onCreate(savedInstanceState); //setContentView(R.layout.activity_photo_selector); @@ -113,7 +113,7 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { DataAndMethods.speaker(getResources().getString(R.string.res_photo_selector), TextToSpeech.QUEUE_FLUSH); try { // might want to read file name here @@ -128,7 +128,7 @@ protected void onResume() { super.onResume(); } @Override - protected void onPause() { + public void onPause() { Timber.d("ACTIVITY: "+ "PhotoSelector Paused"); super.onPause(); } diff --git a/gradle.properties b/gradle.properties index 5a22726..066b66d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,5 @@ android.useAndroidX=true # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +gitlab_maven_repo_url=https://gitlab.com/api/v4/projects/45979364/packages/maven \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 61bd59c..ee2d159 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,10 +10,33 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { + url gitlab_maven_repo_url + credentials(HttpHeaderCredentials) { + name = "Deploy-Token" + value = tokenFromKeystore("gitlab_maven_repo_deployToken") + } + authentication { + header(HttpHeaderAuthentication) + } + } } } +def tokenFromKeystore(String propertyKey) { + def token = "" + def keystorePropertyFile = file("keystore.properties") + if (keystorePropertyFile.exists()) { + def keystoreProperties = new Properties() + keystoreProperties.load(keystorePropertyFile.newDataInputStream()) + if (keystoreProperties.containsKey(propertyKey)) { + token = keystoreProperties.getProperty(propertyKey) + } + } + + return token +} rootProject.name = "IMAGE-Monarch" diff --git a/starter_code/MyOwnRenderer.java b/starter_code/MyOwnRenderer.java index 3e12584..c218534 100644 --- a/starter_code/MyOwnRenderer.java +++ b/starter_code/MyOwnRenderer.java @@ -44,7 +44,7 @@ public class MyOwnRenderer extends BaseActivity implements MediaPlayer.OnComplet private GestureDetectorCompat mDetector; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @@ -57,7 +57,7 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Log.d("ACTIVITY", "Exploration Resumed"); try { // Code Snippet @@ -75,7 +75,7 @@ protected void onResume() { super.onResume(); } @Override - protected void onPause() { + public void onPause() { Log.d("ACTIVITY", "BasicPhotoMapRenderer Paused"); super.onPause(); } diff --git a/starter_code/MyOwnSelector.java b/starter_code/MyOwnSelector.java index 7a9328f..0bbb7b5 100644 --- a/starter_code/MyOwnSelector.java +++ b/starter_code/MyOwnSelector.java @@ -41,13 +41,13 @@ // Launcher activity; switches mode of application public class MyOwnSelector extends BaseActivity implements MediaPlayer.OnCompletionListener { - private BrailleDisplay brailleServiceObj = null; + private SelfBraillingManager brailleServiceObj = null; private GestureDetectorCompat mDetector; @SuppressLint("WrongConstant") @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); super.onCreate(savedInstanceState); @@ -70,14 +70,14 @@ public void onCompletion(MediaPlayer mediaPlayer) { @Override - protected void onResume() { + public void onResume() { Log.d("ACTIVITY", "MyOwnSelector Resumed"); DataAndMethods.speaker("My Own Selector"); DataAndMethods.makePseudoServerCall(); super.onResume(); } @Override - protected void onPause() { + public void onPause() { Log.d("ACTIVITY", "MyOwnSelector Paused"); super.onPause(); }