Control linux desktop volume with Android device

BrunoVol – An Android application that allows the user to control the volume on their linux desktop/laptop, just for fun but also very useful for myself! Its still very draft and simple, feel free to use it and do as you please with it.

Android App

code: https://github.com/BrunoX/BrunoVol

apk: http://carlc.uk/brunovol.apk

The app places a persistent notification in the status bar that has 4 buttons: Volume Down, Volume Up, Mute, Settings.

The settings screen simply allows the user to enter the IP address of their linux computer. It also allows the user to deactivate the persistent notification.

Java app

code: https://github.com/BrunoX/BrunoVolServer

jar: http://carlc.uk/brunovol.jar

The java app listens on a socket waiting for instructions from the Android app. It using Runtime exec to run ‘amixer’, passing volume parameters.

Both the android app and the java app are hard-coded to use port 1025, but you can change that very easily if you compile it yourself. Its sending udp packets over the socket connection. Don’t run the java app on windows it wont work.

Here’s how to use it…

  1. download the jar file onto your linux computer (tested on mint/debien) and run it from the command line with:  java -jar /path/to/brunovol.jar
  2. download the apk file and install onto your android device (android api >16 device only)
  3. launch the android app and enter the IP address of the linux computer, click save*
  4. toggle the enabled button
  5. drag down the status bar and try the buttons, it should adjust the system volume of the linux computer.

* if you don’t enter the IP before toggling ‘enable’, and then were to click on the volume controls in the status bar, it might bug out as I didn’t handle every edge case for the time being.

I’m keen to know where it does/doesn’t function correctly so post a comment on this article telling me if it worked for you and what gear you are testing the whole thing on such as: linux distro, android version, device model and any errors or such that you may be worth mentioning. It should work on any linux computer that uses amixer (from alsa)

SOX and BASH

Bruno torso shell script.

Using SOX to generate random audio video using its spectrogram


#!/bin/bash

n=1;
baseone=$(shuf -i 500-3000 -n 1)
basetwo=$(shuf -i 100-3000 -n 1)

type=$(( $RANDOM % 10 + 1 ))

#type=10

rate=$(shuf -i 1024-192000 -n 1)

wavs=$(shuf -i 4-75 -n 1)

#wavs=10

while [ $n -le $wavs ]
do

filename=note$n.wav
spectroname=spectro$n.png

noteone=$(($baseone + $n * 2))
notetwo=$(($basetwo * $n))

if [ "$type" -gt "5" ]
then
sox -r $rate -n $filename synth 0.5 sine $noteone-$notetwo sawtooth $baseone-$basetwo sin $noteone sin 50-120 spectrogram -o $spectroname
else
reverb=$(shuf -i 1-40 -n 1)
sox -r $rate -n $filename synth 0.5 sine $noteone-$notetwo trapezium $noteone sawtooth $noteone sin $notetwo tremolo 30 reverb $reverb flanger triangle spectrogram -o $spectroname
fi

n=$((n+1))

done

sox /var/www/html/uploads/*.wav out.wav

#create a =nother single wav and mix it with out.wav
otherwavlength=`awk 'BEGIN{printf("%0.2f", '$wavs' * '0.5')}'`
sox -r $rate -n other.wav synth $otherwavlength sawtooth $baseone-$basetwo flanger 0.9 0.9 4.0 0.23 1.3 chorus 0.7 0.9 55.0 0.4 0.25 2.0 -t
sox -m other.wav out.wav new.wav fade p 0 0 2

#rename the png files (0001, 0002, etc)
a=1
for i in *.png; do
new=$(printf "%04d.png" ${a})
mv ${i} ${new}
a=$((a+1))
done

#each image will display for a rate of 2 per second

avconv -y -i new.wav -r 2 -i %4d.png -c:v libvpx -b:v 1M -vf crop=900:585:0:0 -c:a libvorbis bruno.webm

Get a random BBC Headline from the RSS / XML

Get  random headline from the BBC using the DocumentFactory


ArrayList<NewsItem> items = new ArrayList<>();
try{
   DocumentBuilder builder = DocumentBuilderFactory.newInstance()
      .newDocumentBuilder();
   URL u = new URL("http://feeds.bbci.co.uk/news/technology/rss.xml");
   Document doc = builder.parse(u.openStream());
   NodeList nodes = doc.getElementsByTagName("item");
   for(int i = 0; i < nodes.getLength(); i++){
      Element element = (Element) nodes.item(i);
      NewsItem currentStory = new NewsItem(getElementValue(element, "title"),
         getElementValue(element, "description"), getElementValue(element, "link"),
         getElementValue(element, "pubDate"));
      items.add(currentStory);
   }
}
catch(Exception ex){
   if(ex instanceof java.net.ConnectException){
   }
}
Random random = new Random();
NewsItem item = items.get(random.nextInt(items.size() - 1));
return item;

Change Status Bar to Custom Drawable

Change the Android statusbar to a custom drawable on Lollipop devices.

by Napalm.

statusbar

StatusBarView


public class StatusBarView extends View
{
	private int mStatusBarHeight;

	public StatusBarView(Context context)
	{
		this(context, null);

	}

	public StatusBarView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		if(Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP){
			setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
		}
	}

	@Override
	public WindowInsets onApplyWindowInsets(WindowInsets insets)
	{
		if(Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.LOLLIPOP){
			mStatusBarHeight = insets.getSystemWindowInsetTop();
			return insets.consumeSystemWindowInsets();
		}
		return insets;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),mStatusBarHeight);
	}
}

Values-v21.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

	<style name="AppTheme" parent="BaseAppTheme">
		<item name="android:windowDrawsSystemBarBackgrounds">true</item>
		<item name="android:statusBarColor">@android:color/transparent</item>
	</style>

</resources>

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical"
	tools:context=".MainActivity"
	>
	<com.example.StatusBarView
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:background="@drawable/top_gradient"
		/>
        <!--etc -->
</LinearLayout>

top_gradient.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle"
	>
	<gradient
		android:type="linear"
		android:startColor="#ff7300"
		android:centerColor="#77000000"
		android:endColor="#000000"
		android:centerX="0.5"
		android:centerY="0.3"
		android:angle="0"
		/>
</shape>

//… etc …

Pidgin Messenger and Google Chat “Not Authorized”

To allow Pidgin Messenger to work with Google chat/Google talk, you must enabled access to less trusted apps.

Login to your Google account and visit this link: https://myaccount.google.com/

Signing in -> Access for less secure apps -> Turn On

Now Pidgin Messenger will connect to Google chat.

Get Version Code from android apk file using aapt

Use aapt to get the version code from an apk

/sdk/build-tools/21.1.2/aapt d badging /path/to/file.apk

Facebook apps for Android: generating hash using keytool

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

(This will generate the hash for your debug keystore, default password = android)

Improved TextView Observer Design Pattern

In the previous post we explicitly register each observer to the subject. it is more useful to have the observers register and unregister themselves once the views are attached and detached from the screen respectively. This means we never need to worry about adding extra code to deal with unregistering a particular observer during lifecycle events. Here is an improved UIConfigAwareTextView that does that

public class UIConfigAwareTextView extends TextView implements UIConfigObserver
{
	public UIConfigAwareTextView(Context context)
	{
		this(context, null);
	}
	
	public UIConfigAwareTextView(Context context, AttributeSet attrs)
	{
		this(context, attrs, android.R.attr.textViewStyle);
	}
	
	public UIConfigAwareTextView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
	}
	
	@Override
	protected void onAttachedToWindow()
	{
		super.onAttachedToWindow();
		if(getContext() instanceof UIConfigGetter){
			((UIConfigGetter)getContext()).getUIConfig().registerObserver(this);
		}
	}
	
	@Override
	protected void onDetachedFromWindow()
	{
		if(getContext() instanceof UIConfigGetter){
			((UIConfigGetter)getContext()).getUIConfig().unregisterObserver(this);
		}
		super.onDetachedFromWindow();
	}
	
	@Override
	public void update(UIConfig uiConfig)
	{
		this.setTextColor(uiConfig.getFontColor());
	}
}

Also here is a more complete UIConfig model that uses a Handler and synhronizes the observers list. This version will also notify observers once they are added to the observer list so as to ensure they always recieve the latest font color as soon as the view is attached. In order to achieve notifying single observers we can add another method to the UIConfigSubject interface (scroll down for this)

public class UIConfig implements UIConfigSubject
{
	private static final String TAG = UIConfig.class.getSimpleName();
	
	private ArrayList&lt;UIConfigObserver&gt; mObservers = new ArrayList&lt;UIConfigObserver&gt;();
	private Object mObserversLock = new Object();
	private Handler mHandler = null;
	private boolean mPostPending = false;
	
	/** UIConfig properties */
	private int mFontColor;
	
	public UIConfig()
	{
		//
	}
	
	public void setHandler(Handler handler)
	{
		mHandler = handler;
		if(mPostPending){
			mPostPending = false;
			notifyObservers();
		}
	}
	
	@Override
	public void registerObserver(UIConfigObserver observer)
	{
		synchronized (mObserversLock){
			mObservers.add(observer);
			notifyObservers();
		}
	}
	
	@Override
	public void unregisterObserver(UIConfigObserver observer)
	{
		synchronized (mObserversLock){
			mObservers.remove(observer);
		}
	}
	
	@Override
	public void notifyObservers()
	{
		synchronized (mObserversLock){
			if(mHandler != null){
				mHandler.post(new NotifyAllRunnable());
			}
			else{
				mPostPending = true;
			}
		}
	}
	
	@Override
	public void notifyObserver(UIConfigObserver observer)
	{
		mHandler.post(new NotifySingleRunnable(observer));
	}
	
      	private class NotifySingleRunnable implements Runnable
	{
		
		private UIConfigObserver mNewestObserver;
		
		
		public NotifySingleRunnable(UIConfigObserver observer)
		{
			mNewestObserver = observer;
		}
		
		@Override
		public void run()
		{
			Log.w(TAG, "Notifying Single observer.");
			mNewestObserver.update(UIConfig.this);
		}
	}
	
	private class NotifyAllRunnable implements Runnable
	{
		public NotifyAllRunnable()
		{
			//
		}
		
		@Override
		public void run()
		{
			Log.w(TAG, "Notifying " + mObservers.size() + " observers.");
			for(UIConfigObserver ob : mObservers){
				ob.update(UIConfig.this);
			}
		}
	}
	
	public void copyProperties(UIConfig uiConfig)
	{
		setFontColor(uiConfig.getFontColor());
	}
	
	public void setFontColor(int fontColor)
	{
		this.mFontColor = fontColor;
		notifyObservers();
	}

	public int getFontColor()
	{
		return mFontColor;
	}
}

Here is the revised interface

public interface UIConfigSubject
{
	public void registerObserver(UIConfigObserver observer);
	
	public void unregisterObserver(UIConfigObserver observer);
	
	public void notifyObservers();
	
        //This allows us to notify observers independently
	public void notifyObserver(UIConfigObserver observer);
}
Tagged , , , ,

Observer design pattern in Android / Java

The following is an example of how to use observer pattern in java on the Android platform.

Observer pattern (from wikipedia):

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems

The scenario
Imagine we are writing an app that needs the ability to change the color of every TextView on the screen at runtime. At first we might start to write code that allows us to keep a reference to every view and then call the setTextColor() on every single view systematically each time we want to change the color. The problem with this is that there could be many TextView’s on the screen, including ListView’s that contain TextView’s and fragments that contain TextView’s…this could start to get very messy! Observer Pattern can solve this problem.

In our example we will make a custom TextView that is setup to be an observer. We will also create a UIConfig class, this will be the subject of observation. We will make our custom TextView’s register as observers to the subject by adding themselves to a List that is contained in the subject (the UIConfig class). By doing this we can automagically call a method inside our observers whenever a particular change occurs in the subject.

STEP 1 – Create an Interface that our UIConfig object (the subject) will implement

public interface UIConfigSubject {

     public void registerObserver(UIConfigObserver observer);

     public void removeObserver(UIConfigObserver observer);

     public void notifyObservers();
}

STEP 2 – Create an interface that each of our TextView’s (the observers) will implement

public interface UIConfigObserver{

     public void update(UIConfig uiConfig);
}

Now lets build a couple of concrete classes that will implement these interfaces.

Firstly, here is how we make the UIConfig class, a class that is a subject of observation to any class that has implemented the above UIConfigObserver interface and registered itself as an observer (notice the List member which holds a reference to each observer)

public class UIConfig implements UIConfigSubject{

     //we keep a list of current observers.
     //Any class that implements the UIConfigObserver interface can be 
     //added to the list, its not just limited to our custom TextView!
     private List<UIConfigObserver> mObservers = new ArrayList<UIConfigObserver>();

     private String mFontColor;

     public UIConfig(String color){
          mFontColor = color;
     }

     public String getFontColor(){
          return mFontColor;
     }

     public void setFontColor(String fontColor){

          this.mFontColor = fontColor;

          //Whenever our color changes we simply call the notify method to call the update methods...
          notifyObservers();
     }

     @Override
     public void registerObserver(UIConfigObserver observer){
          mObservers.add(observer);
     }

     @Override
     public void removeObserver(UIConfigObserver observer){
          mObservers.remove(observer);
     }

     @Override
     public void notifyObservers(){

          //We just loop through the list of observers and call their update()
          for(UIConfigObserver ob : mObservers){
               ob.update(this);
          }
     }
}

Next lets extend TextView and make a custom view that is ready to observe the UIConfig by means of implementing the UIConfigObserver interface

public class UIConfigAwareTextView extends TextView implements UIConfigObserver{

    public UIConfigAwareTextView(Context context){
        this(context, null);
    }
     
    public UIConfigAwareTextView(Context context, AttributeSet attrs){
        this(context, attrs, android.R.attr.textViewStyle);
    }
     
    public UIConfigAwareTextView(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
    }

     //Whenever the UIConfig objects notify() method is called, this will be called
     @Override
     public void update(UIConfig uiConfig){
          this.setTextColor(Color.parseColor(uiConfig.getFontColor()));
     }
}

Here is how we create some UIConfigAwareTextView’s and register them as observers of a UIConfig object

...
UIConfigAwareTextView tv1 = (UIConfigAwareTextView)findViewById(R.id.tv1);
UIConfigAwareTextView tv2 = (UIConfigAwareTextView)findViewById(R.id.tv2);

UIConfig uiConfig = new UIConfig("#FFFFFF");

uiConfig.registerObserver(tv1);
uiConfig.registerObserver(tv2);
...
//Lets change the color

uiConfig.setFontColor("#FF0000");

//All registered UIConfigAwareTextView's are now red!
...

Now whenever the setFontColor() is called on our UIConfig object our UIConfigAwareTextView’s will have their update() method called and their text color will change! Groovy eh?

How to make this work if our UIConfigAwareTextView is inside a fragment…

Create another interface which will be implemented on the Activity that is holding the fragment. This will be used in order to expose the UIConfig inside the activity to its child fragments.

public interface UIConfigGetter{

     public UIConfig getUIConfig();
}

Now consider the following Fragment, it will hold a UIConfigGetter that is initialized to the parent activity inside the fragments onAttach() method (remember that we must implement the above interface onto the Activity in order for this to work)

public class MyFragment extends Fragment{

     private UIConfigGetter mUIconfigGetter;

     private UIConfigAwareTextView mTv1;

     public static MyFragment newInstance(){

          MyFragment myFragment = new MyFragment();
          return myFragment;
     }

     @Override
     public void onAttach(Activity activity){
          super.onAttach(activity);

          if(activity instanceof UIConfigGetter){
               //Get a reference to the UIConfig interface implemented on the Activity
               mUIconfigGetter = (UIConfigGetter)activity;
          }
     }

     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState){

          return inflater.inflate(R.layout.my_layout, container, false);
     }

     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState){
          super.onViewCreated(view, savedInstanceState);

          mTv1 = new (UIConfigAwareTextView)view.findViewById(R.id.mTv1);

          //Register the view as an observer
          mUIconfigGetter.getUIConfig().registerObserver(mTv1);
     }
}

What if we want to use our UIConfigAwareTextView inside a listview?

We register the TextView’s that are being used in the getView() method of the adapter as observers. As long as we have a reference to the UIConfigGetter interface we are good to go!

For example:

private class MyBaseAdapter extends BaseAdapter{
     ...
     public View getView(int position, View convertView, ViewGroup parent){
			
          ViewHolder viewHolder;
          if(convertView == null){
               convertView = mInflater.inflate(R.layout.gridview_awards_cell, parent, false);
               viewHolder = new ViewHolder();	
               viewHolder.tv = (UIConfigAwareTextView)convertView.findViewById(R.id.tv);		
               viewHolder.tv.setTextColor(Color.parseColor(mUIconfigGetter.getUIConfig().getFontColor()));
               
               //The UIConfigGetter would be initialized inside the fragment onAttach() as before
               mUIconfigGetter.getUIConfig().registerObserver(viewHolder.tv);
               convertView.setTag(viewHolder);
          }
          else{
               viewHolder = (ViewHolder)convertView.getTag();
          }			
          viewHolder.award.setText(mData.get(position).getAwardName());
          return convertView;
     }
     ...
}
Tagged , , , ,

Eclipse OutOfMemoryError

You can increase the amount of memory available to the VM by making the following changes in the eclipse.ini file

-XX:MaxPermSize=500m
-Xms1024m
-Xmx2048m

Tagged , ,