UNESCO Hackathon at FOSSASIA Summit in Singapore

Join the UNESCO Open Data Hackathon at the FOSSASIA Summit, create open source apps and games that tackle climate change, environment and sustainable development challenges, and win awesome prizes! The hackathon takes place from Saturday 24 March to Sunday 25 March 2018 at the Lifelong Learning Institute in Singapore. We are specifically interested in applications and games that set an example for others who could replicate solutions in other countries, and in particular in the Mekong countries, to tackle the sustainable development challenges. It is our goal to engage the developer community to develop innovative applications in open source by leveraging the open data and knowledge available. We are inviting developers, designers, open source contributors, bloggers, journalists and all FOSSASIA community members to be part of the UNESCO Hackathon. We are especially encouraging applications from the Mekong region to join the contest. The hackathon is open for all and awesome prizes are waiting for you! For participants from outside of Singapore we have the possibility to host them in a Singapore hostel. Please apply here. The number is limited. UNESCO encourages the application of women and girls. How do I sign up? 1. Get your ticket to the Event on eventyay.com. 2. Sign up on Devpost. 3. Join the Gitter channel at https://gitter.im/fossasia/hackathon (requires login with Github). 4. Find team members and create your team preferably at least 3 members and maximum 5 contributors. You are also welcome to sign up and then wait until the Presentation of Ideas on Saturday before deciding to join a team, however we'd encourage you to form/join a team in advance if you already have an idea that you'd like to work on. 5. Join the event at the Lifelong Learning Institute on Saturday, March 24 at the opening at 2.00 pm until 10.00 pm and on Sunday, March 25 from 9.00 am until 5.00 pm. Visit the website at unesco.sciencehack.asia and stay connected, join the event on Facebook and Meetup and follow FOSSASIA on Twitter. UNESCO Hackathon Schedule Hackathon Opening: March 24, 2018 12.00 Registration Opens 14:00 Opening 14.10 Intro of Background, Rules and Prizes 14:20 Presentation of Ideas, Teams and Team Building Activities 15:00 Begin of Hacking Activities 19.30 Dinner 22:00 Closing of Space Hackday: March 25, 2018 08:00 - 09:00 Breakfast 09:00 - 13:00 Hack Activities Continue 13:00 - 13:30 Lunch 13:30 - 15:00 Hacking Continues 14:00 Submission Form Closes 15:15 - 16:00 Presentation of Outcome 16:00 Judges Withdraw for Consultation 16:30 Award Announcement and Ceremony 17:00 Summit Closing Location/Venue Lifelong Learning Institute Address: 11 Eunos Road 8, Singapore 408601 Prizes Prizes are awarded for three teams, and each team prize with a value of 1000 SGD. Win cool gear, hardware, raspis, Arduinos and more! Project Submission Requirements For the expected outcome of the hack, the applications or games shall be open source and use open data to tackle the climate change, environment and sustainable development challenges. They shall address one or several of the following requirements: Respond to pressing environmental challenges…

Continue ReadingUNESCO Hackathon at FOSSASIA Summit in Singapore

Filling Audio Buffer to Generate Waves in the PSLab Android App

The PSLab Android App works as an oscilloscope and a wave generator using the audio jack of the Android device. The implementation of the oscilloscope in the Android device using the in-built mic has been discussed in the blog post “Using the Audio Jack to make an Oscilloscope in the PSLab Android App” and the same has been discussed in the context of wave generator in the blog post “Implement Wave Generation Functionality in the PSLab Android App”. This post is a continuation of the post related to the implementation of wave generation functionality in the PSLab Android App. In this post, the subject matter of discussion is the way to fill the audio buffer so that the resulting wave generated is either a Sine Wave, a Square Wave or a Sawtooth Wave. The resultant audio buffer would be played using the AudioTrack API of Android to generate the corresponding wave. The waves we are trying to generate are periodic waves. Periodic Wave: A wave whose displacement has a periodic variation with respect to time or distance, or both. Thus, the problem reduces to generating a pulse which will constitute a single time period of the wave. Suppose we want to generate a sine wave; if we generate a continuous stream of pulses as illustrated in the image below, we would get a continuous sine wave. This is the main concept that we shall try to implement using code. Initialise AudioTrack Object AudioTrack object is initialised using the following parameters: STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purposes we are using stream music. Every stream has its own maximum and minimum volume level.   SAMPLING RATE: It is the rate at which the source samples the audio signal. BUFFER SIZE IN BYTES: Total size of the internal buffer in bytes from where the audio data is read for playback. MODES: There are two modes- MODE_STATIC: Audio data is transferred from Java to the native layer only once before the audio starts playing. MODE_STREAM: Audio data is streamed from Java to the native layer as audio is being played. getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode. minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); audioTrack = new AudioTrack(       AudioManager.STREAM_MUSIC,       SAMPLING_RATE,       AudioFormat.CHANNEL_OUT_MONO,       AudioFormat.ENCODING_PCM_16BIT,       minTrackBufferSize,       AudioTrack.MODE_STREAM); Fill Audio Buffer to Generate Sine Wave Depending on the values in the audio buffer, the wave is generated by the AudioTrack object. Therefore, to generate a specific kind of wave, we need to fill the audio buffer with some specific values. The values are governed by the wave equation of the signal that we want to generate. public short[] createBuffer(int frequency) {   short[] buffer = new short[minTrackBufferSize];   double f = frequency;   double q = 0;   double level = 16384;   final double K = 2.0 * Math.PI / SAMPLING_RATE;   for (int i = 0; i < minTrackBufferSize; i++) {         f += (frequency - f) / 4096.0;         q += (q < Math.PI) ?…

Continue ReadingFilling Audio Buffer to Generate Waves in the PSLab Android App

Export Sensor Data from the PSLab Android App

The PSLab Android App allows users to log data from the sensors connected to the PSLab hardware device. Sensor Data is stored locally but can be exported in various formats. Currently the app supports exporting data in .txt and .csv (comma-separated values) format. Exported data can be used by other users or scientists to study or analyze the data. Data can also be used by other softwares like Python, GNU octave, Matlab to further process it or visualise it in 3D. In this post, we will discuss how to export the locally stored realm data in .txt or .csv format. We will take the data of MPU6050 sensor as an example for understanding how locally logged data is exported. Query Local Realm Data We have attached a long click listener to sensor list view that detects which list item is selected. Clicking any sensor from sensor list for slightly longer than usual would result in a dialog popping up with the option to Export Data: Results in exporting data in a format which is selected in App settings Share Data: Shares sensor data with other users or on social media (yet to be implemented) As soon as the Export Data option is selected from the dialog, sensor data of the corresponding sensor is queried. The data model of the sensor and how it's saved in the local realm database is discussed in the post Sensor Data Logging in the PSLab Android App. RealmResults<DataMPU6050> results = realm.where(DataMPU6050.class).findAll(); Once we get the required data, we need to write it in .txt or .csv format depending on what the user has selected as a preference in App Settings. Getting User Preference from App Settings The format in which the sensor data should be exported is presented to the user as a preference in App Settings. Currently the app supports two formats .txt and .csv. private String format; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); String formatValue = preferences.getString("export_data_format_list", "0"); if ("0".equals(formatValue))   format = "txt"; else   format = "csv"; Export Data in .txt Format To export the sensor data in .txt format, we need to create a .txt file in the external storage. folder variable is a path to PSLab Android folder in the external storage. If the folder doesn’t exist, it will be created. File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "PSLab Android"); After getting reference of the app folder in the external storage, we would create a text file in the PSLab Android folder. As soon as the text file is created, we initialize the FileOutputStream object to write data into the text file. The sensor data that was queried in the previous section is written into the text file just created. Finally after the complete sensor data is written, the stream is closed by stream.close() method. FileOutputStream stream = null; File file = new File(folder, "sensorData.txt"); try {   stream = new FileOutputStream(file);   for (DataMPU6050 temp : results) {       stream.write((String.valueOf(temp.getAx()) + " " + temp.getAy() + " " + temp.getAz() + " " +               temp.getGx()…

Continue ReadingExport Sensor Data from the PSLab Android App

Sensor Data Logging in the PSLab Android App

The PSLab Android App allows users to log data from sensors connected to the PSLab hardware device. The Connected sensors should support I2C, SPI communication protocols to communicate with the PSLab device successfully. The only prerequisite is the additional support for the particular sensor plugin in Android App. The user can log data from various sensors and measure parameters like temperature, humidity, acceleration, magnetic field, etc. These parameters are useful in predicting and monitoring the environment and in performing many experiments. The support for the sensor plugins was added during the porting python communication library code to Java. In this post,  we will discuss how we logged real time sensor data from the PSLab Hardware Device. We used Realm database to store the sensor data locally. We have taken the MPU6050 sensor as an example to understand the complete process of logging sensor data. Creating Realm Object for MPU6050 Sensor Data The MPU6050 sensor gives the acceleration and gyroscope readings along the three axes X, Y and Z. So the data object storing the readings of the mpu sensor have variables to store the acceleration and gyroscope readings along all three axes. public class DataMPU6050 extends RealmObject {   private double ax, ay, az;   private double gx, gy, gz;   private double temperature;   public DataMPU6050() {  }   public DataMPU6050(double ax, double ay, double az, double gx, double gy, double gz, double temperature) {       this.ax = ax;       this.ay = ay;       this.az = az;       this.gx = gx;       this.gy = gy;       this.gz = gz;       this.temperature = temperature;   }  // getter and setter for all variables } Creating Runnable to Start/Stop Data Logging To sample the sensor data at 500ms interval, we created a runnable object and passed it to another thread which would prevent lagging of the UI thread. We can start/stop logging by changing the value of the boolean loggingThreadRunning on button click. TaskMPU6050 is an AsyncTask which reads each sample of sensor data from the PSLab device, it gets executed inside a while loop which is controlled by boolean loggingThreadRunning. Thread.sleep(500) pauses the thread for 500ms, this is also one of the reason to transfer the logging to another thread instead of logging the sensor data in UI thread. If such 500ms delays are incorporated in UI thread, app experience won’t be smooth for the users. Runnable loggingRunnable = new Runnable() {   @Override   public void run() {       try {           MPU6050 sensorMPU6050 = new MPU6050(i2c);           while (loggingThreadRunning) {               TaskMPU6050 taskMPU6050 = new TaskMPU6050(sensorMPU6050);               taskMPU6050.execute();              // use lock object to synchronize threads               Thread.sleep(500);           }       } catch (IOException   InterruptedException e) {           e.printStackTrace();       }   } }; Sampling of Sensor Data We created an AsyncTask to read each sample of the sensor data from the PSLab device in the background thread. The getRaw() method read raw values from the sensor and returned an ArrayList containing the acceleration and gyro values. After the values were read successfully, they were updated in the data card in the foreground which was visible to the user. This data card acts as a…

Continue ReadingSensor Data Logging in the PSLab Android App

Implement Wave Generation Functionality in The PSLab Android App

The PSLab Android App works as an Oscilloscope using the audio jack of Android device. The implementation for the scope using in-built mic is discussed in the post Using the Audio Jack to make an Oscilloscope in the PSLab Android App. Another application which can be implemented by hacking the audio jack is Wave Generation. We can generate different types of signals on the wires connected to the audio jack using the Android APIs that control the Audio Hardware. In this post, I will discuss about how we can generate wave by using the Android APIs for controlling the audio hardware. Configuration of Audio Jack for Wave Generation Simply cut open the wire of a cheap pair of earphones to gain control of its terminals and attach alligator pins by soldering or any other hack(jugaad) that you can think of. After you are done with the tinkering of the earphone jack, it should look something like shown in the image below. If your earphones had mic, it would have an extra wire for mic input. In any general pair of earphones the wire configuration is almost the same as shown in the image below. Android APIs for Controlling Audio Hardware AudioRecord and AudioTrack are the two classes in Android that manages recording and playback respectively. For Wave Generation application we only need AudioTrack class. Creating an AudioTrack object: We need the following parameters to initialise an AudioTrack object. STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purpose we are using stream music. Every stream has its own maximum and minimum volume level. SAMPLING RATE: it is the rate at which source samples the audio signal. BUFFER SIZE IN BYTES: total size in bytes of the internal buffer from where the audio data is read for playback. MODES: There are two modes MODE_STATIC: Audio data is transferred from Java to native layer only once before the audio starts playing. MODE_STREAM: Audio data is streamed from Java to native layer as audio is being played. getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode. private int minTrackBufferSize; private static final int SAMPLING_RATE = 44100; minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); audioTrack = new AudioTrack(       AudioManager.STREAM_MUSIC,       SAMPLING_RATE,       AudioFormat.CHANNEL_OUT_MONO,       AudioFormat.ENCODING_PCM_16BIT,       minTrackBufferSize,       AudioTrack.MODE_STREAM); Function createBuffer() creates the audio buffer that is played using the audio track object i.e audio track object would write this buffer on playback stream. Function below fills random values in the buffer due to which a random signal is generated. If we want to generate some specific wave like Square Wave, Sine Wave, Triangular Wave, we have to fill the buffer accordingly. public short[] createBuffer(int frequency) {   // generating a random buffer for now   short[] buffer = new short[minTrackBufferSize];   for (int i = 0; i < minTrackBufferSize; i++) {       buffer[i] = (short) (random.nextInt(32767) + (-32768));   }   return buffer; } We created a write() method and passed the audio buffer created in above step as an argument to…

Continue ReadingImplement Wave Generation Functionality in The PSLab Android App

Implementing Experiment Functionality in PSLab Android

Using the PSLab Hardware Device, users can perform experiments in various domains like Electronics, Electrical, Physics, School Level experiments, etc. These experiments can be performed using functionalities exposed by hardware device like Programmable Voltage Sources, Programmable Current Source, etc. In this post we will try implementing the functionality to perform an experiment using the PSLab Hardware Device and the PSLab Android App. Let us take the Ohm's law experiment as an example and see how it's implement using the  PSLab Android App. Ohm's law states that the current through a conductor between two points is directly proportional to the voltage across the two points, effectively using a constant of proportionality called Resistance (R) where, R = V / I Schematic Layout to perform Ohm’s law experiment The Ohm's law experiment requires a variable current, so a seekbar is provided to change the current coming from PCS channel, values of which are continuously reflected in the TextView next to it. Implementation The Read button has a listener attached to it. Once it is clicked, the currentValue is updated with the value parsed from the seekbar progress and the selectedChannel variable is assigned from the spinner. These variables are used by the background thread to change the current supplied by current source (PCS pin) of the device and to read the updated voltage from the selected channel of the device. btnReadVoltage.setOnClickListener(new View.OnClickListener() {   @Override   public void onClick(View v) {       selectedChannel = channelSelectSpinner.getSelectedItem().toString();       currentValue = Double.parseDouble(tvCurrentValue.getText().toString());       if (scienceLab.isConnected()) {           CalcDataPoint calcDataPoint = new CalcDataPoint();           calcDataPoint.execute();       } else {           Toast.makeText(getContext(), "Device not connected", Toast.LENGTH_SHORT).show();       }   } }); CalcDataPoint is an AsyncTask which does all the underlying work like setting the current at the PCS channel, reading the voltage from the CH1 channel and triggering the update of the data points on the graph. private class CalcDataPoint extends AsyncTask<Void, Void, Void> {   @Override   protected Void doInBackground(Void... params) {       scienceLab.setPCS((float) currentValue);       switch (selectedChannel) {           case "CH1":               voltageValue = scienceLab.getVoltage("CH1", 5);               break;           case "CH2":               voltageValue = scienceLab.getVoltage("CH2", 5);               break;           case "CH3":               voltageValue = scienceLab.getVoltage("CH3", 5);               break;           default:               voltageValue = scienceLab.getVoltage("CH1", 5);       }       x.add((float) currentValue);       y.add((float) voltageValue);       return null;   }   @Override   protected void onPostExecute(Void aVoid) {       super.onPostExecute(aVoid);       updateGraph();   } } updateGraph() method is used to update the graph on UI thread. It creates a new dataset from the points which were added by the background thread and refreshes the graph with it using the invalidate() method. private void updateGraph() {   tvVoltageValue.setText(df.format(voltageValue));   List<ILineDataSet> dataSets = new ArrayList<>();   List<Entry> temp = new ArrayList<>();   for (int i = 0; i < x.size(); i++) {       temp.add(new Entry(x.get(i), y.get(i)));   }   LineDataSet dataSet = new LineDataSet(temp, "I-V Characteristic");   dataSet.setColor(Color.RED);   dataSet.setDrawValues(false);   dataSets.add(dataSet);   outputChart.setData(new LineData(dataSets));   outputChart.invalidate(); } Roadmap We are planning to add an option to support multiple trials of the same experiment and save each trails for further reference. App flow to perform experiment is based on Science Journal app by Google. Resources Article on Ohm’s law and Power on electronics-tutorial To know more about Voltage, Current, Resistance and Ohm’s law, head on to detailed…

Continue ReadingImplementing Experiment Functionality in PSLab Android

Performing the Experiments Using the PSLab Android App

General laboratory experiments can be performed using core functionalities offered by the PSLab hardware device like Programmable Voltage Sources, Programmable Current Source, Analog to Digital Converter, Frequency Counter, Function Generators, etc. In this post we will  have a brief look on a general laboratory experiment and how we can perform it using the  PSLab Android App and the PSLab hardware device. We are going to take Zener I-V Characteristics Curve experiment as an example to understand how we can perform a general experiment using the PSLab device. First, we will  look at the general laboratory experiment and it's format. Then we will see how that experiment can be performed using the PSLab Android App and the PSLab Hardware Device. Experiment Format of General Experiment in Laboratory AIM: In this experiment, our aim is to observe the relation between the voltage and the corresponding current that was generated. We will then plot it to get the dependence. Apparatus: A Zener Diode A DC Voltage Supplier Bread Board 100 ohm resistor 2 multimeter for measuring current and voltages Connecting wires Theory: A Zener Diode is constructed for operation in the reverse breakdown region.The relation between I-V is almost linear in this case, Vz = Vz0 + Iz * Rz , where Rz is the dynamic resistance of the zener at the operating point and Vz0 is the voltage at which the straight-line approximation of the I-V characteristic intersects the horizontal axis. After reaching a certain voltage, called the breakdown voltage, the current increases drastically even for a small change in voltage. However, there is no appreciable change in voltage accompanying this current change. So, when we plot the graph, we get a curve which is very near to the x-axis and nearly parallel to it until a particular potential value, called the Zener potential, is reached. After the Zener potential Vz value, there will be a sudden change and the graph becomes exponential. Procedure: Construct the circuit as shown in figure below Now, start increasing the voltage until a reading in the multimeter for current can be obtained. Note that reading. Now, start increasing the input voltage and take the corresponding current readings. Using the set of readings observed,  construct a V vs I graph. This graph gives us the I-V characteristics. The slope of the curve at any point gives the dynamic resistance at that voltage. Result: The Characteristic curve has been verified after plotting V-I data points on the graph. Experiment format in PSLab Android App We have a ViewPager that renders two fragments: Experiment Doc- It consists of information like the Aim of experiment, Schematic, Output screenshot that we will get after the experiment has been performed. Experiment Setup- It consists of the setup to configure the PSLab device. This fragment is analogous to the experiment apparatus of the laboratory.   Below is a gif showing the experiment doc of the Zener I-V experiment which is to be performed using the PSLab device. It consists of a schematic and…

Continue ReadingPerforming the Experiments Using the PSLab Android App

Using the Audio Jack to make an Oscilloscope in the PSLab Android App

The PSLab Android App allows users to access functionality provided by the PSLab hardware device, but in the interest of appealing to a larger audience that may not have immediate access to the device, we’re working on implementing some additional functionalities to perform experiments using only the hardware and sensors that are available in most android phones. The mentors suggested that the audio jack (Microphone input) of phones can be hacked to make it function as an Oscilloscope. Similarly, the audio output can also be used as a 2-channel arbitrary waveform generator. So I did a little research and found some articles which described how it can be done. In this post, I will dive a bit into the following aspects - AudioJack specifications for android devices Android APIs that provide access to audio hardware of device Integrating both to achieve scope functionality Audio Jack specification for android devices In a general audio jack interface, the configuration CTIA(LRGM - Left, Right, Ground, Mic) is present as shown in the image below. Some interfaces also have OMTP(LRMG - Left, Right, Mic, Ground) configuration in which the common and mic inputs are interchanged. In the image, Common refers to ground. If we simply cut open the wire of a cheap pair of earphones (stolen from an airplane? ;) ) , we  will gain access to all terminals (Left, Right, Common, Mic Input) illustrated in the image below Android APIs that provide access to audio hardware of device AudioRecord and AudioTrack are two classes in android that manage recording and playback respectively. We require only AudioRecord to implement scope functionality. We shall first create an object of the AudioRecord class, and use that object to read the audio buffer as and when required. Creating an AudioRecord object: we need the following parameters to initialise an AudioRecord object. SAMPLING_RATE: Almost all mobile devices support sampling rate of 44100 Hz. In this context, the definition is number of audio samples taken per second. RECORDER_AUDIO_ENCODING: Audio encoding describes bit representation of audio data. Here we used PCM_16BIT encoding this means stream of bits generated from PCM are segregated in a set of 16 bits. getMinimumBufferSize() returns minimum buffer size in byte units required to create an AudioRecord object successfully. private static final int SAMPLING_RATE = 44100; private static final int RECORDING_CHANNEL = AudioFormat.CHANNEL_IN_MONO; private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT; private AudioRecord audioRecord = null; private int minRecorderBufferSize; minRecorderBufferSize = AudioRecord.getMinBufferSize(SAMPLING_RATE, RECORDING_CHANNEL, RECORDER_AUDIO_ENCODING); audioRecord = new AudioRecord(       MediaRecorder.AudioSource.MIC,       SAMPLING_RATE,       RECORDING_CHANNEL,       RECORDER_AUDIO_ENCODING,       minRecorderBufferSize); audioRecord object can be used to read audio buffer from audio hardware using read() method. minRecorderBuffer size is in byte units and 2 bytes constitute a short in JAVA. Thus size of short buffer needed is half the total number of bytes. short[] audioBuffer = new short[minRecorderBufferSize / 2]; audioRecord.read(audioBuffer, 0, audioBuffer.length); Now audioBuffer has the audio data as a signed 16 bit values. We need to process the buffer data and plot the processed data points on chart to completely implement scope functionality.…

Continue ReadingUsing the Audio Jack to make an Oscilloscope in the PSLab Android App

Making Custom Change Listeners in PSLab Android

In this post we are going to learn how to make custom change listeners. There are many use cases for custom change listeners like if you want to initiate some action when some variable’s value is changed. In PSLab android app, this was required during initialisation of PSLab hardware device, it takes about 3-4 seconds to initialise the device which includes reading calibration data from device and process it. So before starting the initialisation process, app notifies user with the message, “Initialising Wait …” and after initialisation is done, user is notified with the message “Initialisation Completed”. There might be other ways to accomplish this but I found making a custom change listener for boolean and trigger notifying user action on change of boolean value to be most organised way to do it. Another way I can think of is to pass the fragment reference to the class  constructor for which the object is to be made. And Views need to be made public for access from that object to change status after some work is done. Let’s look at an example, we would change status in a fragment after some task in object instantiation is completed. Implementation Class with variable on which custom change listener is required: Create a class and declare a variable for which you want to listen the value change to trigger some action. In this example we have created a InitializationVariable class and defined a boolean variable named initialised. Define an interface inside the class and that’s where the trick lies. When you set/change the value of the variable through a function setVariable(boolean value) in this case, note that we are triggering the interface method too. public class InitializationVariable {   public boolean initialised = false;   private onValueChangeListener valueChangeListener;   public boolean isInitialised() {       return initialised;   }   public void setVariable(boolean value) {       initialised = value;       if (valueChangeListener != null) valueChangeListener.onChange();   }   public onValueChangeListener getValueChangeListener() {       return valueChangeListener;   }   public void setValueChangeListener(onValueChangeListener valueChangeListener) {       this.valueChangeListener = valueChangeListener;   }   public interface onValueChangeListener {       void onChange();   } } Create an object of above class in activity/fragment: Create an object to the class we just made and attach onValueChangeListener to it. This example shows how it's used in PSLab Android, you can use it anywhere but remember to access view elements from a valid context. public static InitializationVariable booleanVariable; public class HomeFragment extends Fragment {   @BindView(R.id.tv_initialisation_status)   TextView tvInitializationStatus;   public static InitializationVariable booleanVariable;// object whose value change is noted   public static HomeFragment newInstance() {       HomeFragment homeFragment = new HomeFragment();       return homeFragment;   }   @Nullable   @Override   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {       View view = inflater.inflate(R.layout.home_fragment, container, false);       unbinder = ButterKnife.bind(this, view);       return view;   }   @Override   public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {       super.onViewCreated(view, savedInstanceState);       booleanVariable.setValueChangeListener(new InitializationVariable.onValueChangeListener() {           @Override           public void onChange() {               if (booleanVariable.isInitialised())                   tvInitializationStatus.setText("Initialsation Completed");               else                   tvInitializationStatus.setText("Initialising Wait ...");           }       });  } } Now whenever booleanVariable.setVariable(value) is called, it triggers the onValueChangeListener where you can manage the action you wanted to do on value change. This…

Continue ReadingMaking Custom Change Listeners in PSLab Android

Opening Local HTML Files in PSLab Android App

The PSLab Android App allows users to perform experiments using the PSLab device. The experience to perform an experiment should resemble the generic way to perform the experiment. So we associated an Experiment Doc file which the user can refer to while performing experiment. Just like a regular lab manual, the experiment doc contains the AIM, THEORY & FORMULAS, SCHEMATIC, OUTPUT, etc. In the PSLab Desktop App, since there was already a provision for using HTML docs and so I  avoided reinventing the wheel and used those html files as it is.      The problem we faced was how to open a bunch of HTML files with their corresponding CSS, JS files in Android’s webView. There are two ways it can be done: Host the experiment docs on a server and make a request from the android app for the specific experiment doc like Diode I-V, Zener I-V, etc. Put the folder containing all html, CSS, js files in assets folder and request for the HTML doc files locally. The PSLab developer team went with the second option as the availability of  Internet  is necessary for the performing experiment if we follow the first option and so to avoid this dependence on the Internet, we went with the second option and stored HTML docs locally in assets folder. Implementation Put the folder containing all the HTML, CSS, JS files in the assets folder in your android project. In this case the folder is DOC_HTML. Define the WebView in xml and take the webView’s reference in your activity/fragment In xml <WebView   android:id="@+id/perform_experiment_wv"   android:layout_width="match_parent"   android:layout_height="match_parent" /> In activity/fragment webView = (WebView) view.findViewById(R.id.perform_experiment_wv); Load the url in webView in the format as shown below webView.loadUrl("file:///android_asset/DOC_HTML/apps/" + htmlFile); “file:///” acts as resource identifier, so "file:///android_asset/” actually points to “pslab-android/app/src/main/assets/”. From the assets directory, we can a provide route to any HTML file. Here I put all HTML files in apps folder and used the string variable “htmlFile” to point to the specific html file. Similarly html files stored in the external storage can also be accessed but there are some cases you need to handle. For example,if external storage is mounted, you can’t request the html file from external storage. To request html files from external storage, make sure that you have the following permission in your AndroidManifest.xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); Relative to baseDir you can specify the path from your html files, like baseDir + “DOC_HTML/apps” + htmlFile Conclusion Putting HTML files in the assets folder and requesting it by webView’s loadURL() method is the best but there are various drawbacks of using this method like the increase in size of the apk. In our case, the normal apk size was 3MB but after adding the html doc folder it increased to 7MB. It increased by almost an additional size of the html folder added in assets. As it's written, in the android’s project overview guide, the assets folder contains files that should be compiled into an .apk…

Continue ReadingOpening Local HTML Files in PSLab Android App