Linux From Scratch (LFS) is a project that provides you with step-by-step instructions for building your own customized Linux system entirely from source.
You may download the stable book in various formats from the stable book directory.
Sunday, November 29, 2015
Saturday, November 28, 2015
RecyclerView + CardView example: with Button
This example work on last example of "Gallery-like RecyclerView + CardView example" to show how to add a button and OnClickListener in RecyclerView + CardView. A ImageButton is add over the photo on each cell. Once user click on the ImageButton, the corresponding OnClickListener, to show the info of the corresponding photo.
Modify layout/layout_cardview.xml to add a ImageButton.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
card_view:cardCornerRadius="5sp"
card_view:cardElevation="5sp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
android:id="@+id/buttonInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_menu_info_details"
android:background="#00ffffff"/>
</FrameLayout>
</android.support.v7.widget.CardView>
Modify MyRecyclerViewAdapter.java:
- get the reference to the Button in the constructor of RecyclerView.ViewHolder.
- implement the OnClickListener in onBindViewHolder() of MyRecyclerViewAdapter.
package com.blogspot.android_er.androidgallery;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemHolder>{
private List<Uri> itemsUri;
private LayoutInflater layoutInflater;
private Context context;
private OnItemClickListener onItemClickListener;
MainActivity mainActivity;
public MyRecyclerViewAdapter(Context context, MainActivity mainActivity){
this.context = context;
layoutInflater = LayoutInflater.from(context);
itemsUri = new ArrayList<Uri>();
this.mainActivity = mainActivity;
}
@Override
public MyRecyclerViewAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CardView itemCardView = (CardView)layoutInflater.inflate(R.layout.layout_cardview, parent, false);
return new ItemHolder(itemCardView, this);
}
@Override
public void onBindViewHolder(MyRecyclerViewAdapter.ItemHolder holder, final int position) {
final Uri targetUri = itemsUri.get(position);
holder.setItemUri(targetUri.getPath());
if (targetUri != null){
try {
//! CAUTION !
//I'm not sure is it properly to load bitmap here!
holder.setImageView(loadScaledBitmap(targetUri));
holder.btnInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,
"btnInfo clicked:\n"
+ "position:" + position + "\n"
+ targetUri.getLastPathSegment(),
Toast.LENGTH_LONG).show();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
/*
reference:
Load scaled bitmap
http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
*/
private Bitmap loadScaledBitmap(Uri src) throws FileNotFoundException {
//display the file to be loadScaledBitmap(),
//such that you can know how much work on it.
mainActivity.textInfo.append(src.getLastPathSegment() + "\n");
// required max width/height
final int REQ_WIDTH = 150;
final int REQ_HEIGHT = 150;
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(src),
null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, REQ_WIDTH,
REQ_HEIGHT);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeStream(
context.getContentResolver().openInputStream(src), null, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
@Override
public int getItemCount() {
return itemsUri.size();
}
public void setOnItemClickListener(OnItemClickListener listener){
onItemClickListener = listener;
}
public OnItemClickListener getOnItemClickListener(){
return onItemClickListener;
}
public interface OnItemClickListener{
public void onItemClick(ItemHolder item, int position);
}
public void add(int location, Uri iUri){
itemsUri.add(location, iUri);
notifyItemInserted(location);
}
public void clearAll(){
int itemCount = itemsUri.size();
if(itemCount>0){
itemsUri.clear();
notifyItemRangeRemoved(0, itemCount);
}
}
public static class ItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private MyRecyclerViewAdapter parent;
private CardView cardView;
ImageView imageView;
String itemUri;
ImageButton btnInfo;
public ItemHolder(CardView cardView, MyRecyclerViewAdapter parent) {
super(cardView);
itemView.setOnClickListener(this);
this.cardView = cardView;
this.parent = parent;
imageView = (ImageView) cardView.findViewById(R.id.item_image);
btnInfo = (ImageButton) cardView.findViewById(R.id.buttonInfo);
}
public void setItemUri(String itemUri){
this.itemUri = itemUri;
}
public String getItemUri(){
return itemUri;
}
public void setImageView(Bitmap bitmap){
imageView.setImageBitmap(bitmap);
}
@Override
public void onClick(View v) {
final OnItemClickListener listener = parent.getOnItemClickListener();
if(listener != null){
listener.onItemClick(this, getLayoutPosition());
//or use
//listener.onItemClick(this, getAdapterPosition());
}
}
}
}
~ More example of RecyclerView + CardView.
Friday, November 27, 2015
Add and Remove view dynamically, another approach
Last post show a example of "Add and Remove view dynamically", each Remove Button have its own OnClickListener object, each OnClickListener object refer to a specified view.
It's another approach: all Remove Buttons share a common OnClickListener object. Inside the OnClickListener, retrieve the associate addView from the trigger view by calling its getParent() method.
MainActivity.java
activity_main.xml and row.xml, refer to last post "Add and Remove view dynamically, keep track of child views".
It's another approach: all Remove Buttons share a common OnClickListener object. Inside the OnClickListener, retrieve the associate addView from the trigger view by calling its getParent() method.
MainActivity.java
package com.blogspot.android_er.androiddynamicview;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
EditText textIn;
Button buttonAdd;
LinearLayout container;
TextView reList, info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textIn = (EditText)findViewById(R.id.textin);
buttonAdd = (Button)findViewById(R.id.add);
container = (LinearLayout)findViewById(R.id.container);
reList = (TextView)findViewById(R.id.relist);
info = (TextView)findViewById(R.id.info);
info.setMovementMethod(new ScrollingMovementMethod());
buttonAdd.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
LayoutInflater layoutInflater =
(LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View addView = layoutInflater.inflate(R.layout.row, null);
TextView textOut = (TextView)addView.findViewById(R.id.textout);
textOut.setText(textIn.getText().toString());
Button buttonRemove = (Button)addView.findViewById(R.id.remove);
/*
final View.OnClickListener thisListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
info.append("thisListener called:\t" + this + "\n");
info.append("Remove addView: " + addView + "\n\n");
((LinearLayout)addView.getParent()).removeView(addView);
listAllAddView();
}
};
buttonRemove.setOnClickListener(thisListener);
container.addView(addView);
info.append(
"thisListener:\t" + thisListener + "\n"
+ "addView:\t" + addView + "\n\n"
);
*/
buttonRemove.setOnClickListener(commonRemoveOnClickListener);
container.addView(addView);
info.append(
"CommonRemoveOnClickListener:\t" + commonRemoveOnClickListener + "\n"
+ "addView:\t" + addView + "\n"
+ "buttonRemove:\t" + buttonRemove + "\n\n");
listAllAddView();
}
});
}
private void listAllAddView(){
reList.setText("");
int childCount = container.getChildCount();
for(int i=0; i<childCount; i++){
View thisChild = container.getChildAt(i);
reList.append(thisChild + "\n");
}
}
View.OnClickListener commonRemoveOnClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
info.append("this View clicked:\t" + v + "\n");
info.append("this Listener called:\t" + this + "\n");
View thisParentView = (View) v.getParent();
info.append("Remove thisParentView: " + thisParentView + "\n\n");
((LinearLayout)thisParentView.getParent()).removeView(thisParentView);
listAllAddView();
}
};
}
activity_main.xml and row.xml, refer to last post "Add and Remove view dynamically, keep track of child views".
Add and Remove view dynamically, keep track of child views
I have a old example of "Add and Remove view dynamically". Somebody ask how the Remove button keep track of the views. So I modify the example to explain in more details.
In this example, when user click on the Add button, it will create a child View, addView. The addView have a Button, buttonRemove. The buttonRemove have its own OnClickListener object. The OnClickListener object refer to the specified addView when it is created.
That means the OnClickListener object of the buttonRemove in the first child view("abc") not the same object in the second child view("abcdef"), not the same object in the third child view("abcdefghi")...All have its own individual OnClickListener object. And each OnClickListener object refer to a specified addView object. Such that it can keep track of the child Views, addView.
MainActivity.java
layout/activity_main.xml
layout/row.xml, the layout of the child views.
Download the files (Android Studio Format) .
It's another approach to share a common OnClickListener between all buttonRemove.
more:
- Add and Remove view dynamically, with EditText/AutoCompleteTextView inside
In this example, when user click on the Add button, it will create a child View, addView. The addView have a Button, buttonRemove. The buttonRemove have its own OnClickListener object. The OnClickListener object refer to the specified addView when it is created.
That means the OnClickListener object of the buttonRemove in the first child view("abc") not the same object in the second child view("abcdef"), not the same object in the third child view("abcdefghi")...All have its own individual OnClickListener object. And each OnClickListener object refer to a specified addView object. Such that it can keep track of the child Views, addView.
MainActivity.java
package com.blogspot.android_er.androiddynamicview;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
EditText textIn;
Button buttonAdd;
LinearLayout container;
TextView reList, info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textIn = (EditText)findViewById(R.id.textin);
buttonAdd = (Button)findViewById(R.id.add);
container = (LinearLayout)findViewById(R.id.container);
reList = (TextView)findViewById(R.id.relist);
info = (TextView)findViewById(R.id.info);
info.setMovementMethod(new ScrollingMovementMethod());
buttonAdd.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
LayoutInflater layoutInflater =
(LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View addView = layoutInflater.inflate(R.layout.row, null);
TextView textOut = (TextView)addView.findViewById(R.id.textout);
textOut.setText(textIn.getText().toString());
Button buttonRemove = (Button)addView.findViewById(R.id.remove);
final View.OnClickListener thisListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
info.append("thisListener called:\t" + this + "\n");
info.append("Remove addView: " + addView + "\n\n");
((LinearLayout)addView.getParent()).removeView(addView);
listAllAddView();
}
};
buttonRemove.setOnClickListener(thisListener);
container.addView(addView);
info.append(
"thisListener:\t" + thisListener + "\n"
+ "addView:\t" + addView + "\n\n"
);
listAllAddView();
}
});
}
private void listAllAddView(){
reList.setText("");
int childCount = container.getChildCount();
for(int i=0; i<childCount; i++){
View thisChild = container.getChildAt(i);
reList.append(thisChild + "\n");
}
}
}
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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="horizontal"
android:padding="16dp"
tools:context="com.blogspot.android_er.androiddynamicview.MainActivity">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Add" />
<EditText
android:id="@+id/textin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/add" />
</RelativeLayout>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"></LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<TextView
android:id="@+id/relist"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:textStyle="bold"
android:background="#E0E0E0"/>
<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:textStyle="italic"
android:background="#D0D0D0"
android:gravity="bottom"/>
</LinearLayout>
</LinearLayout>
layout/row.xml, the layout of the child views.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Remove"/>
<TextView
android:id="@+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/remove"/>
</RelativeLayout>
Download the files (Android Studio Format) .
It's another approach to share a common OnClickListener between all buttonRemove.
more:
- Add and Remove view dynamically, with EditText/AutoCompleteTextView inside
Thursday, November 26, 2015
socket.getInetAddress() return null on Android 5
Refer to last example of "Simple HTTP server running on Android", it work on Xiaomi Redmi 2 running Android 4.4.4. But somebody report program stopped on Android 5 devices. So I re-test on Nexus 7 running Android 5.1.1. Yes, the app crash! caused by NullPointerException, because socket.getInetAddress() return null.
Modify MainActivity.java to capture socket.getInetAddress() before and after close():
It's found that on Xiaomi Redmi 2 running Android 4.4.4, socket.getInetAddress() keep no change before and after close().
But on Nexus 7 running Android 5.1.1, change to null after close().
So, we have to read socket.getInetAddress() before close().
Modify MainActivity.java to capture socket.getInetAddress() before and after close():
package com.blogspot.android_er.androidhttpserver;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
public class MainActivity extends AppCompatActivity {
EditText welcomeMsg;
TextView infoIp;
TextView infoMsg;
String msgLog = "";
ServerSocket httpServerSocket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
infoIp = (TextView) findViewById(R.id.infoip);
infoMsg = (TextView) findViewById(R.id.msg);
infoIp.setText(getIpAddress() + ":"
+ HttpServerThread.HttpServerPORT + "\n");
HttpServerThread httpServerThread = new HttpServerThread();
httpServerThread.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (httpServerSocket != null) {
try {
httpServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
private class HttpServerThread extends Thread {
static final int HttpServerPORT = 8888;
@Override
public void run() {
Socket socket = null;
try {
httpServerSocket = new ServerSocket(HttpServerPORT);
while(true){
socket = httpServerSocket.accept();
HttpResponseThread httpResponseThread =
new HttpResponseThread(
socket,
welcomeMsg.getText().toString());
httpResponseThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class HttpResponseThread extends Thread {
Socket socket;
String h1;
HttpResponseThread(Socket socket, String msg){
this.socket = socket;
h1 = msg;
}
@Override
public void run() {
BufferedReader is;
PrintWriter os;
String request;
try {
is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
request = is.readLine();
os = new PrintWriter(socket.getOutputStream(), true);
String response =
"<html><head></head>" +
"<body>" +
"<h1>" + h1 + "</h1>" +
"</body></html>";
os.print("HTTP/1.0 200" + "\r\n");
os.print("Content type: text/html" + "\r\n");
os.print("Content length: " + response.length() + "\r\n");
os.print("\r\n");
os.print(response + "\r\n");
os.flush();
InetAddress clientInetAddressBeforeClose = socket.getInetAddress();
socket.close();
InetAddress clientInetAddressAfterClose = socket.getInetAddress();
msgLog += "Request: " + request + "\n";
if(clientInetAddressBeforeClose == null){
msgLog += "clientInetAddressBeforeClose == null\n";
}else{
msgLog += "clientInetAddressBeforeClose = " + clientInetAddressBeforeClose.toString() + "\n";
}
if(clientInetAddressAfterClose == null){
msgLog += "clientInetAddressAfterClose == null\n";
}else{
msgLog += "clientInetAddressAfterClose = " + clientInetAddressAfterClose.toString() + "\n";
}
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
infoMsg.setText(msgLog);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
}
}
It's found that on Xiaomi Redmi 2 running Android 4.4.4, socket.getInetAddress() keep no change before and after close().
But on Nexus 7 running Android 5.1.1, change to null after close().
So, we have to read socket.getInetAddress() before close().
Wednesday, November 25, 2015
Simple HTTP server running on Android
It's my old exercise "Implement simple HTTP server running on Android". Somebody report it's not work, so I re-try it on Android Studio. Actually the code is same as before, and work as expected. Please notice both the server and client have to connect in the same WiFi network.
Updated@2015-11-26:
This code NOT work on Android 5, may be all 5+ version.
Fixed, refer next post "socket.getInetAddress() return null on Android 5".
Work on Xiaomi Redmi 2, running Android 4.4.4
MainActivity.java
layout/activity_main.xml
Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Download the files (Android Studio Format) .
Updated@2015-11-26:
This code NOT work on Android 5, may be all 5+ version.
Fixed, refer next post "socket.getInetAddress() return null on Android 5".
Work on Xiaomi Redmi 2, running Android 4.4.4
MainActivity.java
package com.blogspot.android_er.androidhttpserver;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
public class MainActivity extends AppCompatActivity {
EditText welcomeMsg;
TextView infoIp;
TextView infoMsg;
String msgLog = "";
ServerSocket httpServerSocket;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
welcomeMsg = (EditText) findViewById(R.id.welcomemsg);
infoIp = (TextView) findViewById(R.id.infoip);
infoMsg = (TextView) findViewById(R.id.msg);
infoIp.setText(getIpAddress() + ":"
+ HttpServerThread.HttpServerPORT + "\n");
HttpServerThread httpServerThread = new HttpServerThread();
httpServerThread.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (httpServerSocket != null) {
try {
httpServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "SiteLocalAddress: "
+ inetAddress.getHostAddress() + "\n";
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
return ip;
}
private class HttpServerThread extends Thread {
static final int HttpServerPORT = 8888;
@Override
public void run() {
Socket socket = null;
try {
httpServerSocket = new ServerSocket(HttpServerPORT);
while(true){
socket = httpServerSocket.accept();
HttpResponseThread httpResponseThread =
new HttpResponseThread(
socket,
welcomeMsg.getText().toString());
httpResponseThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private class HttpResponseThread extends Thread {
Socket socket;
String h1;
HttpResponseThread(Socket socket, String msg){
this.socket = socket;
h1 = msg;
}
@Override
public void run() {
BufferedReader is;
PrintWriter os;
String request;
try {
is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
request = is.readLine();
os = new PrintWriter(socket.getOutputStream(), true);
String response =
"<html><head></head>" +
"<body>" +
"<h1>" + h1 + "</h1>" +
"</body></html>";
os.print("HTTP/1.0 200" + "\r\n");
os.print("Content type: text/html" + "\r\n");
os.print("Content length: " + response.length() + "\r\n");
os.print("\r\n");
os.print(response + "\r\n");
os.flush();
socket.close();
msgLog += "Request of " + request
+ " from " + socket.getInetAddress().toString() + "\n";
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
infoMsg.setText(msgLog);
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return;
}
}
}
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidhttpserver.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<EditText
android:id="@+id/welcomemsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Welcome from Android-er" />
<TextView
android:id="@+id/infoip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Download the files (Android Studio Format) .
Introducing Visual Studio Dev Essentials
Visual Studio Dev Essentials is a new free developer offering from Microsoft. A free membership to this program gives you access to a range of benefits including developer tools and services, training and support. This video provides an overview of some key benefits, including Visual Studio Community, Visual Studio Team Services, Pluralsight training, and HackHands live programming help. You'll also learn the easiest way to get started and activate your benefits.
Join now at http://aka.ms/devessentials.
Join now at http://aka.ms/devessentials.
Tuesday, November 24, 2015
Download and run Android Studio 2.0 Preview on Windows 10
This video show how to download and run Android Studio 2.0 Preview from Canary Channel, in parallel with existing installed Android Studio 1.5.
(The Emulator is seem still the old version, not the New Android Emulator)
reference: Android Developers Blog announcement
Related: Install Android Studio 2.0 Preview on Ubuntu Linux, parallel with existing installed Android Studio
Windows 10: add Administrator account in login screen
To add Administrator account in login screen:
- Run Command Prompt as Administrator
- Enter the command:
net user administrator /active:yes
Generate Power Efficiency Diagnostics Report for Windows 10
To generate Power Efficiency Diagnostics Report for Windows 10:
- Run Command Prompt as Administrator
- Enter the command: powercfg -energy -output C:\report.html
- After report generated, you can see C:\report.html for details.
Windows 10 Power User Menu
Power User Menu of Windows 10 (and Windows 8) is a pop-up menu with shortcuts tosome usedful "Power User" Windows tools. You can easy access the "Old Control Panel" here.
To Open Power User Menu,
To Open Power User Menu,
- Right click the Start button, or
- WIN+X: Pressing the WIN (Windows) key and the 'X' key together.
Install Android Studio 2.0 Preview on Ubuntu Linux, parallel with existing installed Android Studio
Android Studio 2.0 Preview is available to download in Canary Channel now. This video show how to download and run in Ubuntu (Ubuntu-GNOME 15.10 on VirtualBox/Windows 10), in parallel with existing installed Android Studio 1.5.
(reference: Android Developers Blog)
Related:
- Download and run Android Studio 2.0 Preview on Windows 10
Monday, November 23, 2015
Wednesday, November 18, 2015
Tuesday, November 17, 2015
Display image in opposite color to Trick your brain
This example inspired by the BBC video "Trick your brain: black and white photo turns to colour! - Colour: The Spectrum of Science".
Load your photo, touch the ImageView to display the image of opposite color, look on the blue dot concentratedly for a moment, then release touch to display the black and white image. MAY BE you will be tricked with a color image. try it:)
APK can be download on bottom of this post.
MainActivity.java
package com.blogspot.android_er.androidimage;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import java.io.FileNotFoundException;
public class MainActivity extends AppCompatActivity {
private static final int RQS_OPEN = 1;
LinearLayout panel;
Button buttonOpen;
ImageView imageView;
BlueDot blueDot;
Bitmap bmNormal, bmGrayScale, bmOpposite;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
panel = (LinearLayout)findViewById(R.id.panel);
buttonOpen = (Button) findViewById(R.id.opendocument);
buttonOpen.setOnClickListener(buttonOpenOnClickListener);
imageView = (ImageView)findViewById(R.id.image);
imageView.setOnTouchListener(imageViewOnTouchListener);
blueDot = (BlueDot)findViewById(R.id.bluedot);
}
View.OnTouchListener imageViewOnTouchListener = new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
//user touch on ImageView
if(bmOpposite != null){
imageView.setImageBitmap(bmOpposite);
blueDot.setVisibility(View.VISIBLE);
}
}else if(event.getAction() == MotionEvent.ACTION_UP){
//user release touch on ImageView
if(bmGrayScale != null){
imageView.setImageBitmap(bmGrayScale);
blueDot.setVisibility(View.INVISIBLE);
}
}
return true;
}
};
View.OnClickListener buttonOpenOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == RQS_OPEN) {
Uri dataUri = data.getData();
int w = imageView.getWidth();
int h = imageView.getHeight();
try {
bmNormal = bmGrayScale = bmOpposite = null;
bmNormal = loadScaledBitmap(dataUri, w, h);
bmGrayScale = getGrayscale(bmNormal);
bmOpposite = getOpposite(bmNormal);
imageView.setImageBitmap(bmGrayScale);
//hide ui control and action bar to make more space for the picture
panel.setVisibility(View.GONE);
getSupportActionBar().hide();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
private Bitmap getGrayscale(Bitmap src){
//Custom color matrix to convert to GrayScale
float[] matrix = new float[]{
0.3f, 0.59f, 0.11f, 0, 0,
0.3f, 0.59f, 0.11f, 0, 0,
0.3f, 0.59f, 0.11f, 0, 0,
0, 0, 0, 1, 0,};
Bitmap dest = Bitmap.createBitmap(
src.getWidth(),
src.getHeight(),
src.getConfig());
Canvas canvas = new Canvas(dest);
Paint paint = new Paint();
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
paint.setColorFilter(filter);
canvas.drawBitmap(src, 0, 0, paint);
return dest;
}
private Bitmap getOpposite(Bitmap src){
int w = src.getWidth();
int h = src.getHeight();
Bitmap dest = Bitmap.createBitmap(w, h, src.getConfig());
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pixel = src.getPixel(x, y);
int oppPixel = Color.argb(
Color.alpha(pixel),
255-Color.red(pixel),
255-Color.green(pixel),
255-Color.blue(pixel));
dest.setPixel(x, y, oppPixel);
}
}
return dest;
}
/*
reference:
Load scaled bitmap
http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
*/
private Bitmap loadScaledBitmap(Uri src, int req_w, int req_h) throws FileNotFoundException {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getBaseContext().getContentResolver().openInputStream(src),
null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, req_w, req_h);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeStream(
getBaseContext().getContentResolver().openInputStream(src), null, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
Custom view to display a blue dot on screen, BlueDot.java
package com.blogspot.android_er.androidimage;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class BlueDot extends View {
Paint paint;
public BlueDot(Context context) {
super(context);
init();
}
public BlueDot(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BlueDot(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int w = canvas.getWidth();
int h = canvas.getHeight();
canvas.drawCircle(w/2, h/2, 25, paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
}
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="5dp"
android:background="@android:color/black"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="android-er.blogspot.com"
android:textStyle="bold" />
<Button
android:id="@+id/opendocument"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Open" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.blogspot.android_er.androidimage.BlueDot
android:id="@+id/bluedot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@id/image"
android:layout_alignBottom="@id/image"
android:layout_alignLeft="@id/image"
android:layout_alignRight="@id/image"
android:visibility="invisible"/>
</RelativeLayout>
</LinearLayout>
Download APK to try.
Convert bitmap to grayscale using matrix and ColorMatrixColorFilter
This example show how to convert bitmap to grayscale using matrix and ColorMatrixColorFilter. Once photo loaded, touch on the ImageView will show the original photo, touch release to show the grayscale photo.
MainActivity.java
package com.blogspot.android_er.androidimage;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.FileNotFoundException;
public class MainActivity extends AppCompatActivity {
private static final int RQS_OPEN = 1;
Button buttonOpen;
ImageView imageView;
Bitmap bmNormal, bmGrayScale;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonOpen = (Button) findViewById(R.id.opendocument);
buttonOpen.setOnClickListener(buttonOpenOnClickListener);
imageView = (ImageView)findViewById(R.id.image);
imageView.setOnTouchListener(imageViewOnTouchListener);
}
View.OnTouchListener imageViewOnTouchListener = new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
//user touch on ImageView
if(bmNormal != null){
imageView.setImageBitmap(bmNormal);
}
}else if(event.getAction() == MotionEvent.ACTION_UP){
//user release touch on ImageView
if(bmGrayScale != null){
imageView.setImageBitmap(bmGrayScale);
}
}
return true;
}
};
View.OnClickListener buttonOpenOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == RQS_OPEN) {
Uri dataUri = data.getData();
int w = imageView.getWidth();
int h = imageView.getHeight();
Toast.makeText(MainActivity.this,
dataUri.toString() + "\n" +
w + " : " + h,
Toast.LENGTH_LONG).show();
try {
bmNormal = bmGrayScale = null;
bmNormal = loadScaledBitmap(dataUri, w, h);
bmGrayScale = getGrayscale(bmNormal);
imageView.setImageBitmap(bmGrayScale);
Toast.makeText(MainActivity.this,
bmGrayScale.getWidth() + " x " + bmGrayScale.getHeight(),
Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
private Bitmap getGrayscale(Bitmap src){
//Custom color matrix to convert to GrayScale
float[] matrix = new float[]{
0.3f, 0.59f, 0.11f, 0, 0,
0.3f, 0.59f, 0.11f, 0, 0,
0.3f, 0.59f, 0.11f, 0, 0,
0, 0, 0, 1, 0,};
Bitmap dest = Bitmap.createBitmap(
src.getWidth(),
src.getHeight(),
src.getConfig());
Canvas canvas = new Canvas(dest);
Paint paint = new Paint();
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
paint.setColorFilter(filter);
canvas.drawBitmap(src, 0, 0, paint);
return dest;
}
/*
reference:
Load scaled bitmap
http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
*/
private Bitmap loadScaledBitmap(Uri src, int req_w, int req_h) throws FileNotFoundException {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getBaseContext().getContentResolver().openInputStream(src),
null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, req_w, req_h);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeStream(
getBaseContext().getContentResolver().openInputStream(src), null, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="5dp"
android:background="@android:color/black"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<Button
android:id="@+id/opendocument"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Open Document of Image/Video" />
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Load photo and scale-down to suit ImageView
This example show how to load photo using Intent.ACTION_OPEN_DOCUMENT, and scale-down to suitable size, to display in ImageView.
MainActivity.java
package com.blogspot.android_er.androidimage;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.FileNotFoundException;
public class MainActivity extends AppCompatActivity {
private static final int RQS_OPEN = 1;
Button buttonOpen;
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonOpen = (Button) findViewById(R.id.opendocument);
buttonOpen.setOnClickListener(buttonOpenOnClickListener);
imageView = (ImageView)findViewById(R.id.image);
}
View.OnClickListener buttonOpenOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, RQS_OPEN);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == RQS_OPEN) {
Uri dataUri = data.getData();
int w = imageView.getWidth();
int h = imageView.getHeight();
Toast.makeText(MainActivity.this,
dataUri.toString() + "\n" +
w + " : " + h,
Toast.LENGTH_LONG).show();
try {
Bitmap bm = loadScaledBitmap(dataUri, w, h);
imageView.setImageBitmap(bm);
Toast.makeText(MainActivity.this,
bm.getWidth() + " x " + bm.getHeight(),
Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
/*
reference:
Load scaled bitmap
http://android-er.blogspot.com/2013/08/load-scaled-bitmap.html
*/
private Bitmap loadScaledBitmap(Uri src, int req_w, int req_h) throws FileNotFoundException {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getBaseContext().getContentResolver().openInputStream(src),
null, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, req_w, req_h);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeStream(
getBaseContext().getContentResolver().openInputStream(src), null, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
Trick your brain: black and white photo turns to colour! - Colour: The Spectrum of Science - BBC
Trick your brain: black and white photo turns to colour! - Colour: The Spectrum of Science - BBC
Programme website: http://bbc.in/1Q7ik5S Look at the photo in the clip. From a picture that contains no colour our brains are able to construct a full colour image.
I tried to develop a example to experience it - Display image in opposite color to Trick your brain.
Sunday, November 15, 2015
Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpURLConnection
This example have the same function of the last post "Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpClient", but using java.net.HttpURLConnection instead of using Android 6.0 removed org.apache.http; to control the on-board in the post "Arduino-er: Standalone ESP8266/ESP-12: web control on-board LED".
APK link can be found on bottom of this post.
MainActivity.java
package com.blogspot.android_er.androidespwebled;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
EditText editIp;
Button btnOn, btnOff;
TextView textInfo1, textInfo2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editIp = (EditText)findViewById(R.id.ip);
btnOn = (Button)findViewById(R.id.bon);
btnOff = (Button)findViewById(R.id.boff);
textInfo1 = (TextView)findViewById(R.id.info1);
textInfo2 = (TextView)findViewById(R.id.info2);
btnOn.setOnClickListener(btnOnOffClickListener);
btnOff.setOnClickListener(btnOnOffClickListener);
}
View.OnClickListener btnOnOffClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
String onoff;
if(v==btnOn){
onoff="/on";
}else{
onoff="/off";
}
btnOn.setEnabled(false);
btnOff.setEnabled(false);
String serverIP = editIp.getText().toString()+ onoff;
TaskEsp taskEsp = new TaskEsp(serverIP);
taskEsp.execute();
}
};
private class TaskEsp extends AsyncTask<Void, Void, String> {
String server;
TaskEsp(String server){
this.server = server;
}
@Override
protected String doInBackground(Void... params) {
final String p = "http://"+server;
runOnUiThread(new Runnable(){
@Override
public void run() {
textInfo1.setText(p);
}
});
String serverResponse = "";
//Using java.net.HttpURLConnection
try {
HttpURLConnection httpURLConnection = (HttpURLConnection)(new URL(p).openConnection());
if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = null;
inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream));
serverResponse = bufferedReader.readLine();
inputStream.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
serverResponse = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
serverResponse = e.getMessage();
}
//
//Using org.apache.http
/*
HttpClient httpclient = new DefaultHttpClient();
try {
HttpGet httpGet = new HttpGet();
httpGet.setURI(new URI(p));
HttpResponse httpResponse = httpclient.execute(httpGet);
InputStream inputStream = null;
inputStream = httpResponse.getEntity().getContent();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream));
serverResponse = bufferedReader.readLine();
inputStream.close();
} catch (URISyntaxException e) {
e.printStackTrace();
serverResponse = e.getMessage();
} catch (ClientProtocolException e) {
e.printStackTrace();
serverResponse = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
serverResponse = e.getMessage();
}
*/
return serverResponse;
}
@Override
protected void onPostExecute(String s) {
textInfo2.setText(s);
btnOn.setEnabled(true);
btnOff.setEnabled(true);
}
}
}
For layout file, refer to last post "Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpClient".
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
NO need to add the code useLibrary 'org.apache.http.legacy' to build.gradle file.
Download the files (Android Studio Format) .
Download APK .
ESP8266/ESP-12 code, refer "Arduino-er: Standalone ESP8266/ESP-12: web control on-board LED".
Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpClient
I have a example in my another blog "Arduino-er: Standalone ESP8266/ESP-12: web control on-board LED". We can control the on-board LED via web. It's Android App to control the on-board using HttpClient.
MainActivity.java
layout/activity_main.xml
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Apache HTTP Client Removed from Android 6.0 release. To keep using org.apache.http.client, we have to add the code useLibrary 'org.apache.http.legacy' to build.gradle file.
Download the files (Android Studio Format) .
ESP8266/ESP-12 code, refer "Arduino-er: Standalone ESP8266/ESP-12: web control on-board LED".
Next:
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpURLConnection.
MainActivity.java
package com.blogspot.android_er.androidespwebled;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
public class MainActivity extends AppCompatActivity {
EditText editIp;
Button btnOn, btnOff;
TextView textInfo1, textInfo2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editIp = (EditText)findViewById(R.id.ip);
btnOn = (Button)findViewById(R.id.bon);
btnOff = (Button)findViewById(R.id.boff);
textInfo1 = (TextView)findViewById(R.id.info1);
textInfo2 = (TextView)findViewById(R.id.info2);
btnOn.setOnClickListener(btnOnOffClickListener);
btnOff.setOnClickListener(btnOnOffClickListener);
}
View.OnClickListener btnOnOffClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
String onoff;
if(v==btnOn){
onoff="/on";
}else{
onoff="/off";
}
btnOn.setEnabled(false);
btnOff.setEnabled(false);
String serverIP = editIp.getText().toString()+ onoff;
TaskEsp taskEsp = new TaskEsp(serverIP);
taskEsp.execute();
}
};
private class TaskEsp extends AsyncTask<Void, Void, String> {
String server;
TaskEsp(String server){
this.server = server;
}
@Override
protected String doInBackground(Void... params) {
final String p = "http://"+server;
runOnUiThread(new Runnable(){
@Override
public void run() {
textInfo1.setText(p);
}
});
String serverResponse = "";
HttpClient httpclient = new DefaultHttpClient();
try {
HttpGet httpGet = new HttpGet();
httpGet.setURI(new URI(p));
HttpResponse httpResponse = httpclient.execute(httpGet);
InputStream inputStream = null;
inputStream = httpResponse.getEntity().getContent();
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(inputStream));
serverResponse = bufferedReader.readLine();
inputStream.close();
} catch (URISyntaxException e) {
e.printStackTrace();
serverResponse = e.getMessage();
} catch (ClientProtocolException e) {
e.printStackTrace();
serverResponse = e.getMessage();
} catch (IOException e) {
e.printStackTrace();
serverResponse = e.getMessage();
}
return serverResponse;
}
@Override
protected void onPostExecute(String s) {
textInfo2.setText(s);
btnOn.setEnabled(true);
btnOff.setEnabled(true);
}
}
}
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<EditText
android:id="@+id/ip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="192.168.43.103" />
<Button
android:id="@+id/bon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="LED ON" />
<Button
android:id="@+id/boff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="LED OFF" />
<TextView
android:id="@+id/info1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="italic" />
<TextView
android:id="@+id/info2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />
</LinearLayout>
uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.
Apache HTTP Client Removed from Android 6.0 release. To keep using org.apache.http.client, we have to add the code useLibrary 'org.apache.http.legacy' to build.gradle file.
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.blogspot.android_er.androidespwebled"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
useLibrary 'org.apache.http.legacy'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
}
Download the files (Android Studio Format) .
ESP8266/ESP-12 code, refer "Arduino-er: Standalone ESP8266/ESP-12: web control on-board LED".
Next:
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpURLConnection.
Apache HTTP Client Removed from Android 6.0 release
Android 6.0 release removes support for the Apache HTTP client. If your app is using this client and targets Android 2.3 (API level 9) or higher, use the HttpURLConnection class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption.
To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle file:
Have to sync Gradle project after you insert the above code in build.gradle file.
Reference: Android 6.0 Changes - Apache HTTP Client Removal
Related examples of using Apache HTTP client and HttpURLConnection:
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using Android 6.0 removed HttpClient
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpURLConnection
To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle file:
android {
useLibrary 'org.apache.http.legacy'
}
Have to sync Gradle project after you insert the above code in build.gradle file.
Reference: Android 6.0 Changes - Apache HTTP Client Removal
Related examples of using Apache HTTP client and HttpURLConnection:
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using Android 6.0 removed HttpClient
- Android App to control Standalone ESP8266/ESP-12 on-board LED, using HttpURLConnection
Saturday, November 14, 2015
VirtualBox auto mount shared folder
The post demonstrate how to "Install Ubuntu GNOME 15.10 on Windows 10/VirtualBox", and also share folder between Windows host and Ubuntu guest user folder, in command line/shell script.
Starting with version 4.0, VirtualBox can mount shared folders automatically. In case on Linux guests, auto-mounted shared folders are mounted into the /media directory, along with the prefix sf_. For example, the shared folder myfiles would be mounted to /media/sf_myfiles on Linux and /mnt/sf_myfiles on Solaris.
Access to auto-mounted shared folders is only granted to the user group vboxsf, which is created by the VirtualBox Guest Additions installer. Hence guest users have to be member of that group to have read/write access or to have read-only access in case the folder is not mapped writable.
(reference: https://www.virtualbox.org/manual/ch04.html#sf_mount_auto)
In order to use the share folder feature, you have to "Insert Guest Additions CD images".
The below video show how to create share folder between host Windows (D:\vbShare) and guest Ubuntu Linux (/media/sf_vbShare), and add current user to the vboxsf group with the command:
$ sudo usermod -a -G vboxsf eric
where:
vboxsf is the user group own the shared folder
eric is the the current user
Starting with version 4.0, VirtualBox can mount shared folders automatically. In case on Linux guests, auto-mounted shared folders are mounted into the /media directory, along with the prefix sf_. For example, the shared folder myfiles would be mounted to /media/sf_myfiles on Linux and /mnt/sf_myfiles on Solaris.
Access to auto-mounted shared folders is only granted to the user group vboxsf, which is created by the VirtualBox Guest Additions installer. Hence guest users have to be member of that group to have read/write access or to have read-only access in case the folder is not mapped writable.
(reference: https://www.virtualbox.org/manual/ch04.html#sf_mount_auto)
In order to use the share folder feature, you have to "Insert Guest Additions CD images".
The below video show how to create share folder between host Windows (D:\vbShare) and guest Ubuntu Linux (/media/sf_vbShare), and add current user to the vboxsf group with the command:
$ sudo usermod -a -G vboxsf eric
where:
vboxsf is the user group own the shared folder
eric is the the current user