Showing posts with label using. Show all posts
Showing posts with label using. Show all posts

Convert ImageView to black and white and set brightness using ColorFilter

| 0 comments |


MainActivity.java
package com.blogspot.android_er.androidcolorfilter;

import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

ImageView imageView;
SeekBar brightnessBar;
TextView brightnessInfo;

PorterDuff.Mode[] optMode = PorterDuff.Mode.values();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imageView = (ImageView)findViewById(R.id.iv);
brightnessBar = (SeekBar)findViewById(R.id.bar_brightness);
brightnessInfo = (TextView)findViewById(R.id.brightness_info);

brightnessBar.setOnSeekBarChangeListener(brightnessBarChangeListener);

setBlackAndWhite(imageView);
}

SeekBar.OnSeekBarChangeListener brightnessBarChangeListener
= new SeekBar.OnSeekBarChangeListener(){

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
setBlackAndWhite(imageView);
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}
};

private void setBlackAndWhite(ImageView iv){

float brightness = (float)(brightnessBar.getProgress() - 255);

float[] colorMatrix = {
0.33f, 0.33f, 0.33f, 0, brightness, //red
0.33f, 0.33f, 0.33f, 0, brightness, //green
0.33f, 0.33f, 0.33f, 0, brightness, //blue
0, 0, 0, 1, 0 //alpha
};

ColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
iv.setColorFilter(colorFilter);

brightnessInfo.setText(String.valueOf(brightness));
}

}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout


android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
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" />

<ImageView
android_id="@+id/iv"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_src="@mipmap/ic_launcher"/>

<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="Brightness"/>

<SeekBar
android_id="@+id/bar_brightness"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_max="512"
android_progress="255"/>

<TextView
android_id="@+id/brightness_info"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_text="Brightness"/>
</LinearLayout>


Related:
- Android example code using ColorFilter

Read More..

Implement dummy Heart Rate Measurement profile using Arduino Due HM 10 for BluetoothLeGatt sample code

| 0 comments |
Previous post "Connect HM-10 (BLE Module) to Android device, with BluetoothLeGatt sample project" show step-by-step to modify Android BluetoothLeGatt sample program, by-pass Heart Rate Measurement profile handling to show function of HM-10.

Here we will send dummy data of Heart Rate Measurement profile by  Arduino Due + HM-10.


First of all, edit BluetoothLeService.java to resume original handling for Heart Rate Measurement profile:
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.android.bluetoothlegatt;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import java.util.List;
import java.util.UUID;

/**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();

private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt;
private int mConnectionState = STATE_DISCONNECTED;

private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTING = 1;
private static final int STATE_CONNECTED = 2;

public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";

public final static UUID UUID_HEART_RATE_MEASUREMENT =
UUID.fromString(SampleGattAttributes.HM_10);

// Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());

} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}

@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}

@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};

private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}

private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);

// This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + " " + stringBuilder.toString());
}
}


/*
Log.v("AndroidLE", "broadcastUpdate()");

final byte[] data = characteristic.getValue();

Log.v("AndroidLE", "data.length: " + data.length);

if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data) {
stringBuilder.append(String.format("%02X ", byteChar));

Log.v("AndroidLE", String.format("%02X ", byteChar));
}
intent.putExtra(EXTRA_DATA, new String(data) + " " + stringBuilder.toString());
}
*/


sendBroadcast(intent);
}

public class LocalBinder extends Binder {
BluetoothLeService getService() {
return BluetoothLeService.this;
}
}

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
}

private final IBinder mBinder = new LocalBinder();

/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}

mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}

return true;
}

/**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}

// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}

final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}

/**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}

/**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}

/**
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* @param characteristic The characteristic to read from.
*/
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}

/**
* Enables or disables notification on a give characteristic.
*
* @param characteristic Characteristic to act on.
* @param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}

/**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null;

return mBluetoothGatt.getServices();
}
}


Connect Arduino Due and HM-10:
HM-10 VCC - Arduino Due 3.3V
HM-10 GND - Arduino Due GND
HM-10 Tx - Arduino Due Rx
HM-10 Rx - Arduino Due Tx


Program on Arduino Due, DueSimHeartRate.ino. It only send dummy heart rate data to serial port.
int LED = 13;
boolean LEDst = false;

byte c;

void setup() {
Serial3.begin(9600);
pinMode(LED, OUTPUT);
digitalWrite(LED, LEDst);
}

void loop() {
delay(1000);
c = (byte)0x00;
Serial3.write(c);
c = (byte)80;
Serial3.write(c);

delay(1000);
c = (byte)0x00;
Serial3.write(c);
c = (byte)81;
Serial3.write(c);

delay(10);
c = (byte)0x00;
Serial3.write(c);
c = (byte)82;
Serial3.write(c);

ToggleLED();
}

void ToggleLED(){
digitalWrite(LED, LEDst = !LEDst);
}


Read More..

Xero keeps global offices connected and nimble using Chromebox for meetings

| 0 comments |


Editors note: It’s been just over a year since we launched Chromebox for meetings, and to celebrate the milestone we’re sharing stories about our customers and their approaches to business, culture and productivity that are bringing them success. In today’s post, online accounting software provider Xero tells how it manages to keep its startup-like efficiency, innovation and feel while expanding globally. To learn more about Chromebox for meetings, join us online at Chrome Live on April 22 and see how companies scale face-to-face meetings across the globe.


Xero was started by several developers nine years ago in an apartment above a coffee shop in Wellington, New Zealand. Today, we have more than 1,000 employees in 15 cities across the U.S., U.K., Australia and New Zealand and provide online accounting software to more than 400,000 global customers. With more than 200 percent five-year average sales growth as of June 2014, our biggest challenge now is managing the fast-paced growth while maintaining our nimble, tech-forward startup culture.

We like to keep work in small groups and move quickly. Our teams work closely on projects even when they’re located in different offices around the world. And since we like to stay on the cutting edge of technology, we’re using Google Apps, which allows us to stay coordinated and productive.

Our pain point in IT was finding a way for teams in different cities and offices to meet and collaborate at the same time. We used a variety of video conferencing technologies, including PCs, HDMI/VGA and projectors. They were difficult to set up, meetings were delayed and productivity suffered. As we continued to grow, this struggle intensified, and we realized that we needed to find a solution fast. We needed to streamline our meeting room setups and get the most out of Hangouts. When we heard about Chromebox for meetings, we jumped at the chance to try it out.

We started with six Chromebox for meetings units. Today, we have nearly a hundred. They’re in every meeting room. We use them for room-to-room conferencing and all hands meetings. The global team uses them to connect every two weeks and the CEO addresses the entire company via Hangout on Air.

Chromebox for meetings allow us to keep things simple. There’s very little infrastructure or wireless connections needed on our side, so no cables necessary. Setup is fast and the integration with Gmail makes joining Hangouts as easy as clicking a button. It’s easy to share documents and work on them together. Then there’s the cost savings. Instead of spending between $40,000 and $60,000 on a video conferencing system, we spent one-tenth of that on a Chromebox and a display.

We may be a larger company now, but we still want to move and act quickly. No matter how large we become, our values align with those of fresh innovative companies that respond rapidly to market demand, customer needs and competition. Thanks to Chromebox for meetings, we can keep the startup feel and agility while growing at breakneck speed.
Read More..

Convert bitmap to grayscale using matrix and ColorMatrixColorFilter

| 0 comments |

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() + " " +
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

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>

Read More..

Basic steps for upgrading source code from SDK 1 5 to 2 1 using Eclipse IDE

| 0 comments |
This is a step by step guide to upgrade one’s source code that was developed for an earlier version of android SDK, as is to work on a new version of SDK installed on your development environment



Pre-requisites:
1. You are using Eclipse IDE - Ganymede
2. You have installed SDK 2.1 on your machine
3. You have upgraded ADT to 0.96 on Eclipse IDE
4. You have pointed the Eclipse IDE to the new SDK 2.1
5. You have changed the default JDK compiler version on Eclipse to 1.6
6. You have created an Android Virtual Device (AVD) that uses the SDK 2.1 / Google API


NOTE: Upgrading SDK and Eclipse installations itself is provided in detail at http://developer.android.com/sdk/index.html & http://developer.android.com/sdk/installing.html


For each project that you have in your eclipse workspace that was written for the earlier version of SDK, you need to do the following for basic upgrade (this does not include the upgrade of APIs that have be deprecated):

Step-by-step guide
1. Right click the project and go to Project Properties -> Android
2. You wil see tha right pane showing the ‘Project Build Target’
3. In this pane you will see either or both: ‘Android 2.1’ & ‘Google APIs’ depending on what you chose to install when upgrading your ADT to 0.96
4. Select Google ‘Android 2.1’ or ‘Google API” whichever is required by your earlier project (note you might have used only Android 1.5 for most projects. You would need Google API only for those projects that use google maps)
5. Then, go to the ‘Project’ menu and click on ‘clean’. Note, this is an optional step. You may have to do this if you get the error ‘Conversion to Dalvik format failed with error 1’.
6. Then, build the project by going to ‘Project’ -> ‘build’
7. You are done. You can now run the earlier Android application using the new SDK 2.1


Read More..

Wyoming strengthens top down communication using Chromebox for meetings

| 0 comments |


Editors note: Today’s guest blogger is Flint Waters, CIO of the State of Wyoming. Since outfitting its conference rooms with Chromebox for meetings, the state spends far less on video conferencing and has transformed how teams communicate and connect with each other and the citizens they serve. See how Wyoming and many other institutions and organizations are using Chromebox for meetings to create a culture of collaboration that translates to greater productivity and better service. 

When I came to work for the State of Wyoming four years ago, five people reported to a contract CIO and operations happened at government speed. The department drew in 300 people from other agencies, and IT teams were assigned to different opportunities. I wanted consolidated IT rather than siloed and needed a culture of urgency and innovation for the state, so we began looking at tools to help us do that. Building on the efforts of the previous administration, the Governor moved all state employees to Google Apps for Work. Today, Chromebox for meetings improves transparency and brings public servants, citizens and elected officials closer together.

Before moving to Chromebox for meetings, we spent $1.5 million a year on a legacy video conferencing system. I felt we weren’t getting enough capability with the technology for the amount of money we were spending. So we phased out all the Tandberg systems and got 178 Chromebox for meetings licenses using a small fraction of our budget.

The cost savings is tremendous, but we’re even more thrilled with the way Chromebox for meetings transforms how we do our jobs and think about public service. Specifically, this technology cuts down on bureaucratic processes and hierarchical protocol. Everyone from the Governor and executives to agency directors use Chromebox for team, cabinet-level and all-hands meetings. Participants can comment and ask questions regardless of their location. We’re also introducing Chromebox for meetings throughout the school system to improve communication between teachers, administrators and students.

With Chromebox for meetings, we’re opening up meetings and making them less formal. We have Chromeboxes in our halls, allowing people to gather around and have impromptu meetings that anybody can join — the closest thing to a watercooler conversation you can get over the Internet. It’s also easier to work together on documents that are viewable on monitors at the stations, making meetings even more interactive and productive.

This technology has also reduced people’s travel time and increased productivity. Wyoming is a large state with a small population and a lot of open road between cities — you can drive for miles on the highway without seeing another car. Chromebox for meetings shortens the distance between offices by allowing people to have a face-to-face interaction without getting in their cars.

I get most excited about the fact that we can be collaborative with Chromebox for meetings. In the future, I’d like to set up an online help desk via live Hangout that’s accessible through the state’s website, so that when web visitors need help, we’d be there to help them right away. We’re connecting people at all levels of government to each other and to the public. With Google tools we can move as fast as our ideas can take us, which is just what we need to bring startup innovation and agility into the halls of government.
Read More..

Get ISO country code for the given latitude longitude using GeoNames Java Client

| 0 comments |
Last example show "Get ISO country code for the given latitude/longitude, using GeoNames Web Service, using HttpURLConnection". GeoNames provide Java Client for GeoNames Webservices to help developers to easily access the geonames web services with java. This post show how to use it in Android.

To use Java Client for GeoNames Webservices in you Android Studio project, you have to download both geonames-1.1.13.jar and jdom-1.0.jar to your local machine. Visit http://www.geonames.org/source-code/ to download.

Then you have to add the JAR modules in your Android Studio Project, refer to the video.


dependencies of :geonames-1.1.13 and :jdom-1.0 will be added in your build.gradle.

Example to get ISO country code for the given latitude/longitude, using GeoNames Java Client:


MainActivity.java
package com.blogspot.android_er.androidgeonames;

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 android.widget.Toast;

import org.geonames.GeoNamesException;
import org.geonames.WebService;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

EditText latText;
EditText lonText;
Button btnFind;
TextView textResult;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latText = (EditText)findViewById(R.id.latText);
lonText = (EditText)findViewById(R.id.lonText);
btnFind = (Button)findViewById(R.id.find);
textResult = (TextView)findViewById(R.id.result);

btnFind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String strLat = latText.getText().toString();
String strLon = lonText.getText().toString();

boolean parsable = true;
Double lat = null, lon = null;

try{
lat = Double.parseDouble(strLat);
}catch (NumberFormatException ex){
parsable = false;
Toast.makeText(MainActivity.this,
"Latitude does not contain a parsable double",
Toast.LENGTH_LONG).show();
}

try{
lon = Double.parseDouble(strLon);
}catch (NumberFormatException ex){
parsable = false;
Toast.makeText(MainActivity.this,
"Longitude does not contain a parsable double",
Toast.LENGTH_LONG).show();
}

if(parsable){
new GeoNamesTask(textResult).execute(lat, lon);
}

}
});
}

private class GeoNamesTask extends AsyncTask<Double, Void, String> {
TextView tResult;

public GeoNamesTask(TextView vResult){
tResult = vResult;
tResult.setText("");
}

@Override
protected String doInBackground(Double... params) {
return queryGeoNames_countryCode(params[0], params[1]);
}

@Override
protected void onPostExecute(String s) {
tResult.setText(s);
}

private String queryGeoNames_countryCode(double latitude, double longitude){
String queryResult = "";

/*
Do not use the demo account for your app or your tests.
It is only meant for the sample links on the documentation pages.
Create your own account instead.
*/
WebService.setUserName("demo");

try {
queryResult = "CountryCode: " + WebService.countryCode(latitude, longitude);
} catch (IOException e) {
e.printStackTrace();
queryResult = e.getMessage();
} catch (GeoNamesException e) {
e.printStackTrace();
queryResult = e.getMessage();
}

return queryResult;
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout


android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
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" />

<EditText
android_id="@+id/latText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_inputType="numberSigned|numberDecimal"
android_hint="Latitude"
android_text="47.03"/>

<EditText
android_id="@+id/lonText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_inputType="numberSigned|numberDecimal"
android_hint="Longitude"
android_text="10.2"/>

<Button
android_id="@+id/find"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="find"/>

<TextView
android_id="@+id/result"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textSize="28dp"
android_textStyle="bold"/>
</LinearLayout>


Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml
 <uses-permission android_name="android.permission.INTERNET"/>




Read More..

Get ISO country code for the given latitude longitude using GeoNames Web Service using HttpURLConnection

| 0 comments |
The GeoNames geographical database covers all countries and contains over eight million placenames that are available for download free of charge. We can get the iso country code for any given latitude/longitude, using GeoNames webservices; api.geonames.org/countryCode?



CountryCode / reverse geocoding

The iso country code of any given point.
Webservice Type : REST 
Url : api.geonames.org/countryCode?
Parameters : lat,lng, type, lang, radius (buffer in km for closest country in coastal areas, a positive buffer expands the positiv area whereas a negative buffer reduces it);
Result : returns the iso country code for the given latitude/longitude
With the parameter type=xml this service returns an xml document with iso country code and country name. The optional parameter lang can be used to specify the language the country name should be in. JSON output is produced with type=JSON
Example http://api.geonames.org/countryCode?lat=47.03&lng=10.2&username=demo 

Important:

  • Do not use the demo account for your app or your tests. It is only meant for the sample links on the documentation pages. Create your own account instead.
  • The parameter username needs to be passed with each request. The username for your application can be registered here. You will then receive an email with a confirmation link and after you have confirmed the email you can enable your account for the webservice on your account page
  • Dont forget to url encode string parameters containing special characters or spaces. (Faq entry on url encoding)
  • ...
read details: http://www.geonames.org/export/web-services.html


Its a example to get the ISO country code of user entered latitude/longitude.


MainActivity.java
package com.blogspot.android_er.androidgeonames;

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.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {

EditText latText;
EditText lonText;
Button btnFind;
TextView textResult;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latText = (EditText)findViewById(R.id.latText);
lonText = (EditText)findViewById(R.id.lonText);
btnFind = (Button)findViewById(R.id.find);
textResult = (TextView)findViewById(R.id.result);

btnFind.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
String strLat = latText.getText().toString();
String strLon = lonText.getText().toString();

new GeoNamesTask(textResult).execute(strLat, strLon);
}
});
}

private class GeoNamesTask extends AsyncTask<String, Void, String> {
TextView tResult;

public GeoNamesTask(TextView vResult){
tResult = vResult;
tResult.setText("");
}

@Override
protected String doInBackground(String... params) {

/*
Do not use the demo account for your app or your tests.
It is only meant for the sample links on the documentation pages.
Create your own account instead.
*/
String queryString =
"http://api.geonames.org/countryCode?lat=" + params[0]
+ "&lng=" + params[1] + "&username=demo";

String s = "";
try {
s = sendQuery(queryString);
} catch (IOException e) {
e.printStackTrace();
s = e.getMessage();
}
return s;
}

@Override
protected void onPostExecute(String s) {
tResult.setText(s);
}


private String sendQuery(String query) throws IOException {
String result = "";

URL searchURL = new URL(query);

HttpURLConnection httpURLConnection = (HttpURLConnection)searchURL.openConnection();
if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader,
8192);

String line = null;
while((line = bufferedReader.readLine()) != null){
result += line;
}

bufferedReader.close();
}

return result;
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout


android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
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" />

<EditText
android_id="@+id/latText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_inputType="numberSigned|numberDecimal"
android_hint="Latitude"
android_text="47.03"/>

<EditText
android_id="@+id/lonText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_inputType="numberSigned|numberDecimal"
android_hint="Longitude"
android_text="10.2"/>

<Button
android_id="@+id/find"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="find"/>

<TextView
android_id="@+id/result"
android_layout_width="match_parent"
android_layout_height="wrap_content" />
</LinearLayout>


Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml
 <uses-permission android_name="android.permission.INTERNET"/>

Next:
GeoNames also provide Java Client for GeoNames Webservices to help developers to easily access the geonames web services with java. Next post "Get ISO country code for the given latitude/longitude, using GeoNames Java Client" show how to use it in Android Studio project.

Related:
- Find addresses of given latitude and longitude using android.location.Geocoder

Read More..

Lookup manufacturer info by MAC address using www macvendorlookup com API

| 0 comments |
Last post show how to "Retrieve IP and MAC addresses of Android WiFi tethering clients from /proc/net/arp". This example show how to get vendor/manufacturer info of the associated MAC addresses.

(You can download runnable APK from link on bottom)


http://www.macvendorlookup.com/api provide API to lookup MAC Address Vendor/Manufacturer info.

Notice that this example havent handle error condition.


MainActivity.java
package com.blogspot.android_er.androidlistclient;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

Button btnRead;
TextView textResult;

ListView listViewNode;
ArrayList<Node> listNote;
ArrayAdapter<Node> adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnRead = (Button)findViewById(R.id.readclient);
textResult = (TextView)findViewById(R.id.result);

listViewNode = (ListView)findViewById(R.id.nodelist);
listNote = new ArrayList<>();
ArrayAdapter<Node> adapter =
new ArrayAdapter<Node>(
MainActivity.this,
android.R.layout.simple_list_item_1,
listNote);
listViewNode.setAdapter(adapter);

listViewNode.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Node node = (Node) parent.getAdapter().getItem(position);
Toast.makeText(MainActivity.this,
"MAC: " + node.mac + " " +
"IP: " + node.ip + " " +
"company: " + node.company + " " +
"country: " + node.country + " " +
"addressL1: " + node.addressL1 + " " +
"addressL2: " + node.addressL2 + " " +
"addressL3: " + node.addressL3 + " " +
"type: " + node.type + " " +
"startHex: " + node.startHex + " " +
"endHex: " + node.endHex + " " +
"startDec: " + node.startDec + " " +
"endDec: " + node.endDec,
Toast.LENGTH_SHORT).show();
}
});

btnRead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new TaskReadAddresses(listNote, listViewNode).execute();
}
});
}



class Node {
String ip;
String mac;

String jsonBody;
String startHex;
String endHex;
String startDec;
String endDec;
String company;
String addressL1;
String addressL2;
String addressL3;
String country;
String type;

String remark;

String queryString = "http://www.macvendorlookup.com/api/v2/";

Node(String ip, String mac){
this.ip = ip;
this.mac = mac;
queryMacVendorLookup();
}

@Override
public String toString() {
return "IP: " + ip + " " + "MAC: " + mac + " " + company + " " + remark;
}

private String sendQuery(String qMac) throws IOException{
String result = "";

URL searchURL = new URL(queryString + qMac);

HttpURLConnection httpURLConnection = (HttpURLConnection) searchURL.openConnection();

if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader,
8192);

String line = null;
while((line = bufferedReader.readLine()) != null){
result += line;
}

bufferedReader.close();
}

return result;
}


private void ParseResult(String json){

try {
JSONArray jsonArray = new JSONArray(json);
JSONObject jsonObject = (JSONObject) jsonArray.get(0);
startHex = jsonObject.getString("startHex");
endHex = jsonObject.getString("endHex");
startDec = jsonObject.getString("startDec");
endDec = jsonObject.getString("endDec");
company = jsonObject.getString("company");
addressL1 = jsonObject.getString("addressL1");
addressL2 = jsonObject.getString("addressL2");
addressL3 = jsonObject.getString("addressL3");
country = jsonObject.getString("country");
type = jsonObject.getString("type");
remark = "OK";

} catch (JSONException e) {
e.printStackTrace();
remark = e.getMessage();
}

}

private void queryMacVendorLookup(){
try {
jsonBody = sendQuery(mac);
ParseResult(jsonBody);
} catch (IOException e) {
e.printStackTrace();
}
}
}

private class TaskReadAddresses extends AsyncTask<Void, Node, Void> {

ArrayList<Node> array;
ListView listView;

TaskReadAddresses(ArrayList<Node> array, ListView v){
listView = v;
this.array = array;
array.clear();
textResult.setText("querying...");
}

@Override
protected Void doInBackground(Void... params) {
readAddresses();

return null;
}

@Override
protected void onPostExecute(Void aVoid) {
textResult.setText("Done");
}

@Override
protected void onProgressUpdate(Node... values) {
listNote.add(values[0]);
((ArrayAdapter)(listView.getAdapter())).notifyDataSetChanged();

}

private void readAddresses() {

BufferedReader bufferedReader = null;

try {
bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));

String line;
while ((line = bufferedReader.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null && splitted.length >= 4) {
String ip = splitted[0];
String mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
Node thisNode = new Node(ip, mac);
publishProgress(thisNode);
}
}
}

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
android_orientation="vertical"
tools_context="com.blogspot.android_er.androidlistclient.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/readclient"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textAllCaps="false"
android_text="Read Ip/MAC addresses"/>

<TextView
android_id="@+id/result"
android_layout_width="match_parent"
android_layout_height="wrap_content"/>

<ListView
android_id="@+id/nodelist"
android_layout_width="match_parent"
android_layout_height="wrap_content"/>
</LinearLayout>


uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml

download filesDownload runnable APK .

Next:
- Get HostName of WiFi hotspot clients, and check if it is still connected.

Read More..

Download and Install JDK8 on Ubuntu 15 10 using update alternatives and also set JAVA HOME

| 0 comments |

This post show how to Install JDK8 on Ubuntu 15.10 (running in VirtualBox hosted on Windows 10).

To download Oracle JDK:
- visit Java SE Downloads page.
- Click to download Java Platform (JDK).
- Accept agreement and sselect download file, jdk-8u65-linux-x64.tar.gz.

Download and unpack in your local storage. /home/eric/jdk1.8.0_65 folder for me.

Setup java and javac update-alternatives:
Run the command:
$ sudo update-alternatives --install /usr/bin/javac javac /home/eric/jdk1.8.0_65/bin/javac 1
$ sudo update-alternatives --install /usr/bin/java java /home/eric/jdk1.8.0_65/bin/java 1

$ sudo update-alternatives --config javac
$ sudo update-alternatives --config java

Where /home/eric/jdk1.8.0_65 is the folder of jdk.

Check the video.


Set JAVA_HOME also:

Setup JAVA_HOME and path to JDK on Linux (Ubuntu in this example), edit the file .bashrc
$ nano .bashrc

Add the line:
export JAVA_HOME=<path to jdk>
export PATH=$JAVA_HOME/bin:$PATH

Where <path to jdk> is the path to the installed JDK.




Alternatively, you can install also Install Oracle java8 on Ubuntu 15.10 via PPA.

Read More..

Generate random String using org apache commons lang3 RandomStringUtils

| 0 comments |

This example show how to generate random String using org.apache.commons.lang3.RandomStringUtils.

You have to download Apache Commons Lang, and add the jar to Android Studio Projects libs. Refer to the video.


package com.blogspot.android_er.androidrandomstring;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.apache.commons.lang3.RandomStringUtils;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button btnGenerate = (Button)findViewById(R.id.gen);
final TextView textResult = (TextView)findViewById(R.id.result);

btnGenerate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textResult.setText("");
for(int i=1; i<20; i++){
String randomString = RandomStringUtils.randomAlphabetic(i) + " ";
textResult.append(randomString);
}
}
});

}
}


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


android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="16dp"
android_orientation="vertical"
tools_context="com.blogspot.android_er.androidrandomstring.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/gen"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_text="Generate Random Strings"/>

<TextView
android_id="@+id/result"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_typeface="monospace"
android_textSize="22sp"/>
</LinearLayout>



Read More..

Hello World to open photo using Intent ACTION OPEN DOCUMENT with FloatingActionButton and Snackbar

| 0 comments |
This example work on last post "Updated Android Studio now provide template of Blank Activity with FloatingActionButton and Snackbar", modify the default Hello World to open image with ACTION_OPEN_DOCUMENT,  display on ImageView.


edit layout/activity_main.xml, to modify the icon of the FloatingActionButton, android:src inside <android.support.design.widget.FloatingActionButton>.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout


android_layout_width="match_parent"
android_layout_height="match_parent" android_fitsSystemWindows="true"
tools_context=".MainActivity">

<android.support.design.widget.AppBarLayout android_layout_height="wrap_content"
android_layout_width="match_parent" android_theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar android_id="@+id/toolbar"
android_layout_width="match_parent" android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary" app_popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main" />

<android.support.design.widget.FloatingActionButton android_id="@+id/fab"
android_layout_width="wrap_content" android_layout_height="wrap_content"
android_layout_gravity="bottom|end" android_layout_margin="@dimen/fab_margin"
android_src="@android:drawable/ic_menu_gallery" />

</android.support.design.widget.CoordinatorLayout>


layout/content_main.xml, its the main layout of our app.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout



android_layout_width="match_parent"
android_layout_height="match_parent"
android_padding="16dp"
android_orientation="vertical"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_showIn="@layout/activity_main"
tools_context=".MainActivity">

<TextView
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_margin="20dp"
android_layout_gravity="center_horizontal"
android_autoLink="web"
android_text="http://android-er.blogspot.com/"
android_textStyle="bold"/>

<ScrollView
android_layout_width="match_parent"
android_layout_height="wrap_content">

<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="vertical">

<TextView
android_id="@+id/texturi"
android_layout_width="wrap_content"
android_layout_height="wrap_content" />
<ImageView
android_id="@+id/image"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_adjustViewBounds="true"/>

</LinearLayout>
</ScrollView>
</LinearLayout>


com.blogspot.android_er.androidhello.MainActivity.java
package com.blogspot.android_er.androidhello;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

private static final int RQS_OPEN_IMAGE = 1;

ImageView imageView;
TextView textUri;

Bitmap bmOriginal = null;
Uri targetUri = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Open photo", Snackbar.LENGTH_LONG)
.setAction("OK", snackbarOnClickListener)
.show();
}
});

textUri = (TextView) findViewById(R.id.texturi);
imageView = (ImageView) findViewById(R.id.image);
}

OnClickListener snackbarOnClickListener = new OnClickListener(){
@Override
public void onClick(View v) {

bmOriginal = null;
imageView.setImageBitmap(null);

Intent intent = new Intent();

if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.KITKAT) {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
} else {
intent.setAction(Intent.ACTION_GET_CONTENT);
}

intent.addCategory(Intent.CATEGORY_OPENABLE);

// set MIME type for image
intent.setType("image/*");

startActivityForResult(intent, RQS_OPEN_IMAGE);

}
};

@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {

if (resultCode == Activity.RESULT_OK) {

Uri dataUri = data.getData();

if (requestCode == RQS_OPEN_IMAGE) {
targetUri = dataUri;
textUri.setText(dataUri.toString());
updatImage(dataUri);
}
}

}

private void updatImage(Uri uri){

if (uri != null){
Bitmap bm;
try {
bm = BitmapFactory.decodeStream(
getContentResolver()
.openInputStream(uri));
imageView.setImageBitmap(bm);
bmOriginal = bm;

} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}



download filesDownload the files (Android Studio Format) .

Related:
- Using Intent.ACTION_OPEN_DOCUMENT, for KitKat API 19 or higher

Next:
- Apply photo effects using Media Effects APIs

Read More..

Display ABI using adb shell getprop ro product cpu abi command

| 0 comments |

Different Android handsets use different CPUs, which in turn support different instruction sets. Each combination of CPU and instruction sets has its own Application Binary Interface, or ABI. The ABI defines, with great precision, how an applications machine code is supposed to interact with the system at runtime.

~ reference: http://developer.android.com/ndk/guides/abis.html


To identify the android device is 32-bit or 64-bit 

Android is going to support 64-bit, but there are so many android devices, how do developer know current device is 32-bit  or 64-bit  ?

Lets begin from  this command:

adb shell getprop ro.product.cpu.abi

getprop is an android utility to retrieve a property via the android property service.

~ referene: https://software.intel.com/en-us/blogs/2014/12/16/how-to-identify-the-image-is-32-bit-or-64-bit-user-space


This video show how the command "adb shell getprop ro.product.cpu.abi" run on device and emulator.




Related:
- List supported ABIs programmatically

Read More..