jueves, 31 de octubre de 2013

Adjust image size to avoid memory issues with images so big

this is the code for decoding images inside a rectangle:


        private 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;
 }
 
 private Bitmap decodeBitmapFromResource(byte[] data,
         int reqWidth, int reqHeight) {

     // First decode with inJustDecodeBounds=true to check dimensions
     final BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     
     BitmapFactory.decodeByteArray(data, 0, data.length,options);

     // Calculate inSampleSize
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
     

     // Decode bitmap with inSampleSize set
     options.inJustDecodeBounds = false;
     
     return BitmapFactory.decodeByteArray(data, 0, data.length,options);
     
 }


Then you can use it in this way:


byte[] data = getImageFromUrl(url);
    
if(data!=null){
    bitmap = decodeBitmapFromResource(data, image_size, image_size);
}

Horizontal View Swipe Eclipse Example

via: http://just-another-blog.net/

The Goal is to implement horizontal View swiping with Tabs in Android like the Google Play Store.
HorizontalViewSwiping
I used the default code from Eclipse.
public class MainActivity extends FragmentActivity {

 /**
  * The {@link android.support.v4.view.PagerAdapter} that will provide
  * fragments for each of the sections. We use a
  * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
  * will keep every loaded fragment in memory. If this becomes too memory
  * intensive, it may be best to switch to a
  * {@link android.support.v4.app.FragmentStatePagerAdapter}.
  */
 SectionsPagerAdapter mSectionsPagerAdapter;

 /**
  * The {@link ViewPager} that will host the section contents.
  */
 ViewPager mViewPager;

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

  // Create the adapter that will return a fragment for each of the three
  // primary sections of the app.
  mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

  // Set up the ViewPager with the sections adapter.
  mViewPager = (ViewPager) findViewById(R.id.pager);
  mViewPager.setAdapter(mSectionsPagerAdapter);

 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 /**
  * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
  * one of the sections/tabs/pages.
  */
 public class SectionsPagerAdapter extends FragmentPagerAdapter {

  public SectionsPagerAdapter(FragmentManager fm) {
   super(fm);
  }

  @Override
  public Fragment getItem(int position) {
   // getItem is called to instantiate the fragment for the given page.
   // Return a DummySectionFragment (defined as a static inner class
   // below) with the page number as its lone argument.
   Fragment fragment = new DummySectionFragment();
   Bundle args = new Bundle();
   args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
   fragment.setArguments(args);
   return fragment;
  }

  @Override
  public int getCount() {
   // Show 3 total pages.
   return 3;
  }

  @Override
  public CharSequence getPageTitle(int position) {
   Locale l = Locale.getDefault();
   switch (position) {
   case 0:
    return getString(R.string.title_section1).toUpperCase(l);
   case 1:
    return getString(R.string.title_section2).toUpperCase(l);
   case 2:
    return getString(R.string.title_section3).toUpperCase(l);
   }
   return null;
  }
 }

 /**
  * A dummy fragment representing a section of the app, but that simply
  * displays dummy text.
  */
 public static class DummySectionFragment extends Fragment {
  /**
   * The fragment argument representing the section number for this
   * fragment.
   */
  public static final String ARG_SECTION_NUMBER = "section_number";

  public DummySectionFragment() {
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
   TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
   dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
   return rootView;
  }
 }

}

The Layout XML for the MainActivity:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<!--
This title strip will display the currently visible page title, as well as the page
titles for adjacent pages.
-->

<android.support.v4.view.PagerTitleStrip
android:id="@+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />

</android.support.v4.view.ViewPager>

The Layout XML for the DummyFragment:
 <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="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity$DummySectionFragment" >

<TextView
android:id="@+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</RelativeLayout>

Instead of the Dummy Fragment you can create your own Fragments.
Just create a new java class that extends “Fragment”.
You can attach your own Fragments to the “MainActivity” that way:
 @Override
 public Fragment getItem(int position) {
  Fragment fragment = new Fragment();
  switch (position) {
  case 0:
   return fragment = new Fragment1();
  case 1:
   return fragment = new Fragment2();
  case 2:
   return fragment = new Fragment3();
  default:
   break;
  }
  return fragment;

That’s all


FIX: I think there's a mistake here: try:
 @Override
 public Fragment getItem(int position) {
  Fragment fragment = new Fragment();
  switch (position) {
  case 0:
   return new Fragment1();
  case 1:
   return new Fragment2();
  case 2:
   return new Fragment3();
  default:
   break;
  }
  return fragment;
via: http://just-another-blog.net/

lunes, 23 de septiembre de 2013

Show ActionBar items within fragments

To enable OnCreateOptionsMenu, onPrepareOptionsMenu, onOptionsItemSelected, in fragment, you have to call setHasOptionsMenu within the fragment’s onCreate() method:
setHasOptionsMenu(true);

martes, 3 de septiembre de 2013

ProgressBar in ActionBar

For using the indeterminate progress bar in the actionbar, just a few steps:

Put requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); before setContentView();

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 
 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
 setContentView(R.layout.extern_main);
}


and use the function setProgressBarIndeterminateVisibility(true); for start the spining and setProgressBarIndeterminateVisibility(false); to stop

martes, 20 de agosto de 2013

Adding location to MapFragment

I am using Reverse Geocoding to get the location, after that, I am placing a marker in the location.

This code adds a location to the MapFragment:

public class AddressMapFragment extends MapFragment {
 
 LatLng location;
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
 }
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View v =  super.onCreateView(inflater, container, savedInstanceState);
  
  Bundle args = getArguments();
  
  if(args!=null){
   String fulladdress = args.getString("fulladdress");
   new ReverseGeocoding().execute(fulladdress);
  }
  
  
  
  return v;
 }
 
 private void initMap(){
     UiSettings settings = getMap().getUiSettings();
     settings.setAllGesturesEnabled(false);
     settings.setMyLocationButtonEnabled(false);
     
     if(location!=null){

      getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(location,16));
      getMap().addMarker(new MarkerOptions().position(location));
     }
 }
 
 public class ReverseGeocoding extends AsyncTask<String, Void, Void>{

  @Override
  protected Void doInBackground(String... params) {
   reverse_geocoding(params[0]);
   return null;
  }
  
  @Override
  protected void onPostExecute(Void result) {
   super.onPostExecute(result);
   
   initMap();
   
  }
  
 }
 
 public void reverse_geocoding(String fulladdress){
  
  Geocoder geo = new Geocoder(getActivity());
  try {
   List<Address> addresses = geo.getFromLocationName(fulladdress, 1);
   if(addresses.size()>0){
    Address address = addresses.get(0); 
    location = new LatLng(address.getLatitude(),address.getLongitude());
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

}

Back to previous fragment with back button

To be able to go back to the previous fragment pressing the back hardware button we have to add the fragment adding null to the backstack.

This is the resultant code:
Fragment fragment = new Fragment();
  
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().add(R.id.content_frame, fragment).addToBackStack(null).commit();
 

jueves, 18 de julio de 2013

How to get view dimensions at onCreate

Hi, Trying to get the dimensions of my RelativeLayout at the onCreate of my Activity without no success, at the begining teh code seemed very easy :
RelativeLayout dashboard = (RelativeLayout)findViewById(R.id.dashboard);
int width = dashboard.getWidth()
no luck!, in this case getWidth() is always 0. Then I tryed to figure out why this happens and I realize that dashboard is not rendered yet, so, I have to find a callback after rendering to get the dashboard width... no luck! onResume didn't work neither, so I was researching through internet and I've found this blog where my problem is perfect solved. I've just going to put the code but you can read the entire article at http://code2thought.blogspot.com.es/2011/01/getting-layout-dimensions-in-android.html
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.dashboard);
  
  RelativeLayout dashboard = (GridLayout)findViewById(R.id.dashboard);
  
  
  dashboard.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
   
   @Override
   public void onGlobalLayout() {
    
    int width = dashboard.getWidth()
    
   }
  });
  
 }
happy coding!

martes, 16 de julio de 2013

GridLayout views out of the screen

Sometimes your views inside a gridlayout are outside the screen, to fix that you can give to your views android:width="0", that way it fits inside the Gridlayout.
<GridLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="2">

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="start|end"
        android:layout_row="0"
        android:text="ASDFASDF"
         />

    <Button
        android:layout_column="1"
        android:layout_gravity="start|end"
        android:layout_row="0"
        android:text="SDAVDFBDFB" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="2"
        android:layout_gravity="fill|center"
        android:layout_row="1"
        android:text="ASDVADFBFDAFEW" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="2"
        android:text="FWEA AWFWEA" />

    <Button
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill"
        android:layout_row="2"
        android:text="BERWEfasf" />

    <Button
        android:layout_width="94dp"
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="3"
        android:text="SDFVBFAEVSAD" />

    <Button
        android:layout_column="0"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="4"
        android:layout_rowSpan="2"
        android:text="GVBAERWEFSD" />

    <Button
        android:width="0dp"
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="3"
        android:layout_rowSpan="2"
        android:text="VSDFAVE SDFASDWA SDFASD" />

    <Button
        android:width="0dp"
        android:layout_column="1"
        android:layout_columnSpan="1"
        android:layout_gravity="fill|center"
        android:layout_row="5"
        android:text="FWEWEGAWEFWAE"/>

</GridLayout>

miércoles, 19 de junio de 2013

Fit map zoom to markers

Exists an easy way in Google Map API v2 to get the correct zoom for all the markers we have in the map:

 public void setZoom(List<LatLng> coords){
                GoogleMap map = getMap();
  LatLngBounds bounds = helper.getBounds(coords);

                int zoom_padding = 20;
  map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, zoom_padding));
 }

        public LatLngBounds getBounds(List<LatLng> coords){
  
  LatLngBounds.Builder builder = new LatLngBounds.Builder();

  for(LatLng coord:coords){
   
    
                 builder.include(coord);
    
  }
  
  return builder.build();
 }

        
easy!

miércoles, 12 de junio de 2013

XML Parser (XmlPullParser)

I feel more confortable parsing JSON, but sometimes I get some services in XML. After reading some articles about parsing and reading the google advices I finally decided to use the class XMLPullParser, not bad, here an example.


First we get the xml
public InputStream getResponseInputStream(String url){
  
  Log.i("URL REQUEST",url);
  URL request;
  try {
   
   request = new URL(url); 
   HttpURLConnection  conn = (HttpURLConnection)request.openConnection(); 
   conn.setConnectTimeout(30000);
   conn.setReadTimeout(30000);
   
   InputStream is = conn.getInputStream();
   return is;

  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  
  return null;
 }

Create the parser
public List<Member> getMemberData(String url){
  
  InputStream is=null;
  try{
   is = getResponseInputStream(url);

   XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
         parser.setInput(is, null);
        
         parser.nextTag();
         List<Member> members = readMembers(parser);
   is.close();
   
   return members;
  
  } catch (Exception e) {
   e.printStackTrace();
   
  }
  
  return null;
 }
Parsing:
private List<Member> readMembers(XmlPullParser parser) throws XmlPullParserException, IOException {
     List<Member> entries = new ArrayList<Member>();

     parser.require(XmlPullParser.START_TAG, null, "root");
     while (parser.next() != XmlPullParser.END_TAG) {
         if (parser.getEventType() != XmlPullParser.START_TAG) {
             continue;
         }
         String name = parser.getName();
         // Starts by looking for the entry tag
         if (name.equals("item")) {
             entries.add(readMemberDetail(parser));
         } else {
             skip(parser);
         }
     }  
     return entries;
 }
 
 private Member readMemberDetail(XmlPullParser parser) throws XmlPullParserException, IOException {
     parser.require(XmlPullParser.START_TAG, null, "item");
     Member member = new Member();

     while (parser.next() != XmlPullParser.END_TAG) {
         if (parser.getEventType() != XmlPullParser.START_TAG) {
             continue;
         }
         
         String localName = parser.getName();
         
         if(localName.equals("id")) member.id = readText(parser,"id");
else if(localName.equals("name")) member.name = readText(parser,"name");
else if(localName.equals("address")) member.address = readText(parser,"address");
else skip(parser);

        
     }
     return member;
 }
And some utils like readText to get the content and skip if we get some tag we don't want to parse
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
     if (parser.getEventType() != XmlPullParser.START_TAG) {
         throw new IllegalStateException();
     }
     int depth = 1;
     while (depth != 0) {
         switch (parser.next()) {
         case XmlPullParser.END_TAG:
             depth--;
             break;
         case XmlPullParser.START_TAG:
             depth++;
             break;
         }
     }
  }
 
 public String readText(XmlPullParser parser, String tag){
  try{
   parser.require(XmlPullParser.START_TAG, null, tag);
      String text = readText(parser);
      parser.require(XmlPullParser.END_TAG, null, tag);
      return text;
  } catch (XmlPullParserException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  
  return null;
 }
More info

martes, 11 de junio de 2013

Unable to open Android Studio because files are locked

"Files in C:\Program Files(x86)\Android\android-studio\system\caches are locked.
Android Studio will not able to start up"

Yeahhh!! this is the error I get when I am trying to open my Android Studio with Windows 7, but, it is as simple to fix as right click over Android Studio icon -> Run as Administrator.

that's all


lunes, 10 de junio de 2013

Enable "More" button on action bar

By default in "pure android" devices you can see at right, in action bar, three gray dots to open the overflow menu. This menu is open in other devices by the hardware button menu.

Those devices with hardware button hide the action bar button.

Sometimes, project managers and clients without any idea about design encourage to us to enable this option in action bar, I am not recommending this feature, if there is no button in action bar is for one reason, it is because the hardware button exists, but if after talking with your pm or your client he is still blind, ok, this is the hack.

Again from Stackoverflow

public class MyApplication extends Application {
 
 @Override
 public void onCreate() {
  super.onCreate();
  
  getOverflowMenu();
 }
 
 protected void getOverflowMenu() {

      try {
         ViewConfiguration config = ViewConfiguration.get(this);
         Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
         if(menuKeyField != null) {
             menuKeyField.setAccessible(true);
             menuKeyField.setBoolean(config, false);
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

}

viernes, 7 de junio de 2013

Shake Listener for Android

Something is not implemented is a default shake listener for Android.
Here is my solution I steal from Stackoverflow

public class ShakerActivity extends Activity implements SensorEventListener{

 private SensorManager mSensorManager;
 private float mAccel; // acceleration apart from gravity
 private float mAccelCurrent; // current acceleration including gravity
 private float mAccelLast; // last acceleration including gravity
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
  
              /* do this in onCreate */
              mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    
              mAccel = 0.00f;
              mAccelCurrent = SensorManager.GRAVITY_EARTH;
              mAccelLast = SensorManager.GRAVITY_EARTH;
  
        }

 @Override
 protected void onResume() {
  super.onResume();
  
  mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
 }
 
 @Override
 protected void onPause() {
  super.onPause();
  
  mSensorManager.unregisterListener(this);
  
 }

 @Override
 public void onAccuracyChanged(Sensor sensor, int accuracy) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void onSensorChanged(SensorEvent event) {
  
  float x = event.values[0];
  float y = event.values[1];
  float z = event.values[2];
  mAccelLast = mAccelCurrent;
  mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
  float delta = mAccelCurrent - mAccelLast;
  mAccel = mAccel * 0.9f + delta; // perform low-cut filter
  
                //if mAccel is greater than 2 mobile is being shaked
  if(mAccel>2){
  
   //TODO: put the code you want to execute when mobile is shaked
  }
  
 }
}

jueves, 6 de junio de 2013

How to post code

First of all, I know this is not related to android but first thing I have to learn is "How to post code" in my blog, making a quick search around google I've found this... http://geektalkin.blogspot.com.es/2009/11/embed-code-syntax-highlighting-in-blog.html let's see if it is working:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

First post

Is supposed that I should put here all my doubts and issues about android development.

I hope some of you can take profit from this, and me too.

 regards