Monday, August 5, 2013

Dynamic DialogFragment - Android

This is frustrating... I've been playing with this stupid DialogFragment for half a day, trying all sort of pieces of code, Questions from StackOverFlow, just to realize, that they are all useless!!

It is as simple as the fact that when using the DialogFragment the LayoutParams of the parent view are not been set, thus renders the dialog badly.

After some thinking about it I've came up with this:

In res/values/stylex.xml:

<resources>
    ...
    <style name="AlertDialogStyle" >
        <item name="android:cacheColorHint">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>
   ...
</resources>

In res/layout/alert_dialog_body.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/tools"
    android:id="@+id/xx"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@android:drawable/alert_dark_frame"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp"
            android:layout_marginTop="5dp"
            android:contentDescription="Separator"
            android:scaleType="fitXY"
            android:src="@drawable/settings_separator"
            app:ignore="HardcodedText" />

        <TextView
            android:id="@+id/AlertBody"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp"
            android:text="TextView"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <Button
            android:id="@+id/DialogButton"
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginTop="15dp"
            android:text="Button" />
    </LinearLayout>

</RelativeLayout>
(The RelativeLayout is the trick...)

Separator Image
In res/drawable/... filename.png





and the Dialog fragment:

public class MyDialogFragment
  extends DialogFragment {
 
 protected final String TAG = getClass().getSimpleName();
 
 private int titleId;
 
 private int bodyId;
 
 private int buttonId;
 
 public MyDialogFragment(int titleId, int bodyId, int buttonId) {
  super();
  this.titleId = titleId;
  this.bodyId = bodyId;
  this.buttonId = buttonId;
 }
 
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  
  View view = inflater.inflate(R.layout.alert_dialog_body, container);
  TextView title = (TextView) view.findViewById(R.id.Title);
  TextView body = (TextView) view.findViewById(R.id.AlertBody);
  Button button = (Button) view.findViewById(R.id.DialogButton);
  
  button.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    getDialog().dismiss();
   }
  });

  button.setText(buttonId);
  title.setText(titleId);
  body.setText(bodyId);
  return view;
 }
 
 @Override
 public void onAttach(android.app.Activity activity) {
  super.onAttach(activity);
 }
 
 @Override
 public void onCreate(android.os.Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AlertDialogStyle);
 }
 
}

And Just in case you would actually want to use this:

MyDialogFragment dialogFragment = new MyDialogFragment(R.string.title,R.string.body,R.string.button_label);
dialogFragment .setCancelable(false);
dialogFragment .show(getSupportFragmentManager(), "Dialog Fragment");

You can check out the code here.

Leave your comments below... :)










Sunday, May 12, 2013

Android Google's Calendar API

That is really sad, I've taken a look at the Google calendar API code, and I just can't believe it... these guys should really read my posts... or at least ask for some advice... of someone else who knows WTH he is doing!!!

I know it is a beta and all, but it is such a horrible beta... it is unbelievable, the hierarchy does not make any sense, when he needs to use inheritance they don't, when they uses it, it is an abuse of the hierarchy mechanism, the use of generics is absolutely wrong, and the use of virtual methods with or without generics is absolutely ridiculous, the code duplicate seem to never end, and the separation to projects seems to be correct but it is not!

I've investigated the API to its core... all the jars attached to the calendar-android-sample, I've attached all the sources to one project, and saw the reflective workaround used to load the classes, there was nothing sophisticated about it.

I've tried to understand how the API works to write a simpler implementation(I'm very good at that!), it is impossible... Google are right to publish their API as open source, why the hell to obfuscate the code if you don't need to ha...? why not just to make a darn mess and no one would be able to understand WTH it does...?

I've tried to avoid writing this, but it burns and upsets me and makes me sad a pile of code written this way.

So I've tried to change my approach... since I want the Calendar API, and I wanted to use it I've tried just to scratch the surface of the sample project... that has made me sad...

I've found the following row:


CalendarList feed = client.calendarList().list().setFields(CalendarInfo.FEED_FIELDS).execute();

can anyone guess WTH it does?

let me tell you, it is a Calendar instance returning a new instance of a CalendarList, which returns a List (not the one you think) of initialized results (which results???), for which you set a field values for the response, for which you have virtual method to cast the return value back to a List, and then calls... execute()...???

execute()????
execute()????
execute()????
execute()????

execute what on a darn list... can you explain... 

ha... yes it inherits from a CalendarRequest with a generic parameter T, oh yes and T is a... wait T can be four different types, now I confused... there are:
  • 1 Clear
  • 1 Instances
  • 1 Query
  • 1 QueryAdd
  • 1 Move
  • 4 Inserts
  • 4 Updates
  • 4 Patches
  • 4 Deletes
  • 6 Gets
Don't you think there might be a better implementation than to override all the darn methods, and cast the return type!

I've always thought Google has the best minds working for them, I've also been to a lecture about the brilliant continues integration system they have build, and trust me it is brilliant, I've meet the guy who designed it, he is very keen, but this just goes to show me, that I my gut was right about not continuing with the attempt to work for Google, I would have for sure ended up resigning, because if this is the infrastructure they release, and I guess they are proud of their "success" (which 'sucks S') then they are lucky to have a lot of money, because it would cost them very much to keep it up!

I know the cost of bad code... I've tried to avoid it for long enough, everywhere I've worked, and seen what bad code can do to huge teams of development... the bottom line... it costs MONEY...

Luckily Google has enough of it :)

Wednesday, April 10, 2013

Android C2DM to GCM

I'm trying... really trying to be nice, to give these guys a chance, but boy, they have done it this time...

Long ago, I've implemented a C2DM Module for Cyborg in less than a day, which was elegant tight, and generic... and a few(3) weeks later, Google has announced that C2DM is dying, and now there is GCM... terrific...

Since I'm short on time, I've implemented a GCM Module for Cyborg, happily using the gcm.jar, and its updates every now and again.

Today, I've actually looked at the code of the gcm.jar, and I was shocked, shocked to find out that this code violates nearly all of my basic coding conventions, this is a sort of code I would have written when I've just started to work with Java, and have tried then to challenge the language conventions.

I've been dealing with very bad code for the last years, but this... I cannot make heads or tails of it...
It is noodles all over the place, using too many static methods and members calling back and forth mixed with broadcast receivers and services all together throwing a swingers party... it is bad Java, mixed with bad Android, if Java could have spoken, it would have shouted "RAPE !!!", it is shamley unbelievable.

This is crazy, I know that "Anyone can cook", but would you actually eat anyone's cooking?
I'm expecting more from you Google!

I'm now in the middle of getting rid of this darn jar file, and I see that the basic registration to the GSF service remained practically the same, they have simply mapped some errors and some use cases, with nasty(ing) if statements.

...
After 2 days...
...

I've finally managed sending a GCM from a device to itself via my server, I've used my JSONer to serialize the and deserialize the JSON, and was surprised to discover that the actual GCM payload MUST be JSON Array...

WTF?

If you already force something, force it to be a JSON Object, and let the people use whatever stupid implementation they want within that object.

Force the payload to be an JSON Array, and to add a key - value extras in the intent which derived from the array... it is an unnecessary overhead!!

Any logical application would use a JSON Object as the payload, and use GSON or any other parser to serialize and deserialize the payload.

Friday, April 5, 2013

Check if an application is installed on the device

This is quite embarrassing... I've used to use the following to perform that check:

private static final String GooglePlayStorePackageName = "com.google.market";

void someMethod() {
    packageManager = getApplication().getPackageManager();
    List<PackageInfo> packages = packageManager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
    for (PackageInfo packageInfo : packages) {
        if (packageInfo.packageName.equals(GooglePlayStorePackageName)) {
            googlePlayStoreInstalled = true;
            break;
        }
    } 
}

Since I cannot stand my own stupidity, and I love to lecture people about how amazing exceptions are and how stupid it is to ignore them, I found that I have done it as well, although not in the same context I lecture people...

Following is the proper code to check whether an application is installed on your device:

protected final boolean isPackageInstalled(String packageName) {
    try {
        application.getPackageManager().getPackageInfo(packageName, 0);
    } catch (NameNotFoundException e) {
        return false;
    }
    return true;
}
As you can see, I've ignored the fact there is a method which throws an exception when it could not find the requested package, which is so dumb of me.

So now I wrapped the method with a boolean returning method, and do use the exception to determine whether the application package is installed or not.

Sunday, February 3, 2013

Android Chronometer

Ha... (With great dissatisfaction...) I can't help but wonder what went through the mind of those who wrote that Chronometer component...

If you have tried to use this component, and have passed the System.currentTimeMillies() value to it, you are in for a surprise, Android's Chronometer is using the elapsed time, from SystemClock.elapsedRealtime().

Now I know I'm a big criticizer, but let me explain... I do understand the issues explained here, but really, who changes the System clock in their application? I've never encountered the need nor a requirement to perform such a system value abuse, and if you need to, double check your architecture!!

I find the component to be unnecessary, I would use a text view, update the time every 750ms, do it in 5 min, and would be still able to sleep at night, but there are people whom want to use this component... so be it.

Keep in mind that you still need to know that the base time needs to be an elapsedRealtime valid value, if you set the currentTimeMillis value you would/might see non-numeric characters in the Chronometer.

To solve this, your application should have something like this:

public class MyApplication
  extends Application {
 
 public static final long CurrentElapsedDelta = SystemClock.elapsedRealtime() - System.currentTimeMillis();
 
 public void setChronometer() {
  // When you want to set the chronometer base time you can use the following from anywhere in your code:
  long calculatedElapsedTime = System.currentTimeMillis() + MyApplication.CurrentElapsedDelta;
 } 
}

I've sketched this out of my head so it might a bit of fixing, I'll update this with a more reliable snippet.

Saturday, January 26, 2013

Android Launching Error

So... I have an Android project in Eclipse, which I haven't touched for a while, and now after a new installation of Eclipse, and other plugin setup, I got the following error while launching the project:
(which used to work 100% of times)

Unable to restore source lookup path - unknown type source container type specified: org.eclipse.cdt.debug.core.containerType.project

This was really frustrating, since I need to deploy a new version for that application, so I've Googled the issue, and found NOTHING...
(I would only expect that much since the scenario to achieve this is quite complicated)

I've tried the standard Eclipse issue solving technics:

  • Close and open the project.
  • Closing and opening Eclipse.
  • Clean Build.
  • Delete and import it back...




You name it, I've tried it.

Last I've noticed that also re-importing the project didn't solve it, I got the idea, that Eclipse has a reference to the project build spec, (from the .project file), referenced by the name of the project, so...
(and this is also the solution :))

  1. I've renamed the project (Added '_' at the end of its name).
  2. Deleted the project from the workspace (Without checking that dangerous check box).
  3. Edited the .project file of the Project, and renamed it back to the original name (Removed that '_').
  4. Re-imported the project into the workspace (Now with the original name).

And that is it...

Just like the lord, Eclipse works in mysterious ways... :)


Wednesday, September 19, 2012

Android calls management.

This was an amazing day today... I've set down with a colleague, to determine the calls states of an Android phone, and here are the results:

Phone state intent/Listener New outgoing call intent
num state number  
Out - OffHook V  
In + Out - OffHook V  
Out x2 - OffHook V  
In V Ringing -  
- OffHook -  
Out + In V Ringing -  
- OffHook -  
In x2 V Ringing -  
- OffHook -  
2 Calls + hang - - -  
2 Calls + swap - - -  
2 Calls + Conf - - -  



Why is this so amazing? 
  • First, the call events are separated to two intents, or one intent and a listener, which is ridicules...
  • Second, the events are so limited, that no function can be based according to the calls...
  • THERE ARE NO EVENTS FOR a second call hang up, call swap, or 2 calls ==> conference... WFT?? (terrible failure)
Note how many '-' are there... how many events are impotent.

I love Android, but the more I dig, the more dirt I find...

 If you have other insights please comment!