Category: Uncategorized

Android – Adding Custom cookies to a WebView

This is just a quick post about adding cookies to a web view. If you’ve ever tried to do this the way most people have said that it should be done, you’ve failed miserably and found this post. 🙂

The way it’s supposed to work is you set the cookie on the CookieManager and then tell the CookieSyncManager to sync.

1
2
CookieManager.getInstance().setCookie(domain, value);
CookieSyncManager.getInstance().sync();

I’ve never got this to work as described. With or without async tasks waiting for the threads to catch up.

Instead, I just add the cookie in the header of all the loadUrl calls.

1
2
3
Map<String, String> headers = new HashMap<String, String>();
headers.put("Cookie", "cookieName=cookieValue;domain=domain.com;path=/;Expires=Thu, 2 Aug 2021 20:47:11 UTC;");
webView.loadUrl("myurl.com", headers );

Caveat: I only need to initially load the appropriate cookie for the request, if you want to cover nested calls from inside the browser, you need to override shouldOverrideUrlLoading.

1
2
3
4
5
6
7
webView.setWebViewClient(new WebViewClient() {
     @Override
     public boolean shouldOverrideUrlLoading(WebView view, String url) {
         view.loadUrl(url, headers);
         return false;
     }
});

If you need to inject the cookie for all requests(including images, js, etc), you’re going to need to override shouldInterceptRequest, which I didn’t have to do so no example, sorry. Good luck!! 🙂

Volley HTTP library for Android with BasicAuth

Volley is an incredibly useful library for Android. It alleviates almost all of the headaches of asynchronous web service calls. Here’s a video of the Google I/O session on Volley that I was lucky enough to attend.

Use git to clone volley from here if you don’t have it already: https://android.googlesource.com/platform/frameworks/volley

I don’t want to go into the intro to Volley, there are tons of those blog posts out there already.

For my latest app that I’m working on, I had to extend it a small bit to get BasicAuth working so I thought I would share an example.

It’s pretty straightforward to get BasicAuth working. You just have to extend the type of request that you want to use. In my case, I had to extend JSONArrayRequest and JSONObjectRequest. Here’s the array extension class as an example. The object version is the same extension, just add the basic auth header in the constructor of the request class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.myapp.services;
 
import java.util.HashMap;
import java.util.Map;
 
import org.json.JSONArray;
 
import android.util.Base64;
 
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.JsonArrayRequest;
 
public class MyArrayRequest extends JsonArrayRequest{
 
	public MyArrayRequest(String url, JSONArray jsonRequest,
			Listener<JSONArray> listener, ErrorListener errorListener) {
		super(url, listener, errorListener);
	}
 
	public MyArrayRequest(String url, Response.Listener<JSONArray> listener,
						Response.ErrorListener errorListener, String username, String password) {
		super(url, listener, errorListener);
		if (username != null && password != null) {
			String loginEncoded = new String(Base64.encode((username + ":" + password).getBytes(), Base64.NO_WRAP));
			this.headers.put("Authorization", "Basic " + loginEncoded);
		}
	}
 
	private Map<String, String> headers = new HashMap<String, String>();
		@Override
		public Map<String, String> getHeaders() throws AuthFailureError {
			return headers;
	}
 
	public void setHeader(String title, String content) {
		headers.put(title, content);
	}
}

I’m going to Google I/O finally!

I always got the short end of the stick on trying to get a ticket in real time. It always is an insta-sellout faster than a Dave Chappelle show. Luckily, a friend called in a favor and I got invited!!

I can’t wait!!!!!!!

One APK to rule them all

I wrote this a while back on a forum post and never posted it here. I figured it was good information and could help other Android nerds as well.

Having one apk to rule them all is a tricky thing to manage. I just recently launched with normal, large, and xlarge layouts along with landscape for large and xlarge. It is not easy, it takes a ton of regression testing, but is totally worth it.

There are some people that are developing separate apps for tablet. I wouldn’t recommend it, personally. Maybe if you pull out all business logic and throw it in a library it may be easier but there would still be a ton of redundant work. Abstract out the work of building out the views, and that will allow you to manage each resolution re-using the same techniques.

One tip is to have a very easily accessible flag that allows you to differentiate which device size you’re running on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//check to see if we have a tablet, large or phone, and then set the global flag
int screenLayout = getResources().getConfiguration().screenLayout;
model.isTablet = 
   ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);
 
//if isTablet is false, check to see if we have a Large device, else
we have a phone
if(model.isTablet == false){
   model.isLarge = 
       ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE);
   if(model.isLarge){
      model.deviceSize = "Large";
   }else{
      model.deviceSize = "Phone";
   }
}else{
   model.deviceSize = "Tablet";
   model.isLarge = false;
}
 
//throw in a isLandscape if that matters as well. 
public boolean isLandscape(Context context) {
   int orientation = context.getResources().getConfiguration().orientation;
   return (orientation == Configuration.ORIENTATION_LANDSCAPE);
}

by using these flags on simple singleton model, you can easily build out the appropriate view for any scenario….except for small. just add a new flag for that 😉

Deep copy of Objects in C# Metro for Windows RT/WoA

Hey Guys! I don’t write blogs as much as I should. I swear I have tons of fun little snippets of code that I use all the time. I just don’t post them. :X

Here’s a great one that I’ve just finally figured out. Deep Copy in C# for Metro is very tricky. All the examples you will find are based on older version of .NET that aren’t included or are deprecated completely in Windows RTM.

Here is a super simple helper function that you can easily throw in an extension class.
 

using System.IO;
using System.Runtime.Serialization;
using Windows.Foundation;

namespace Extensions
{
#pragma warning disable 1591
    public static class ObjectExtension
    {
        public static Object DeepCopy(this Object objectToCopy)
        {
            Object copy;
            DataContractSerializer serializer = new DataContractSerializer(typeof(Object));
            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, objectToCopy);
                ms.Position = 0;
                copy = (Object)serializer.ReadObject(ms);
            }
            return copy;
        }
    }

#pragma warning restore 1591
}

In the example class above, you can easily swap out Object for any Class type you want. I wanted to make this generic but couldn’t get it working. If you can, more power to ya! 🙂

I personally have a Data object in place of Object. One gotcha that you may run into is classes with an ImageSource property or another property that can’t be serialized. You need to add these metadata tags to your class to define which properties are supposed to be copied and which are ignored.

[DataContract]
class DataClass

[DataMember]
String title { get; set;}

[IgnoreDataMember]
ImageSource imageSource { get; set;}

More info can be found in the msdn: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx

Tegra Zone coming soon….

We just announced the Android app that I’ve been working on. It’s getting a ton of press and is really going to be a game changer for the Tegra 2 devices that are coming out. The users are going to get some great differentiated content optimized for their device. There’s a ton of really awesome games finally coming to Android. It’s been pretty bleak in the Market for a long time. 3D games are few and far between. The unreal engine is going to bring PC quality titles to your phone/tablet with cross platform multiplayer over 4g.

http://www.nvidia.com/object/tegra-zone.html

Obligatory press 😛
http://www.engadget.com/2011/01/07/nvidia-shows-off-tegra-2-gameplay-on-atrix-4g-and-optimus-2x/
http://www.androidcentral.com/android-centrals-best-ces-2011
http://androidcommunity.com/nvidia-tegra-zone-coming-to-android-market-20110112/
http://techie-buzz.com/mobile-news/nvidia-tegra-zone-android-market-games.html

Android Gallery and bad performance gotcha

If you’re using the Gallery component from android and experiencing “snappy” animations when your item is selected, you’re most likely doing too much in the UI thread OnItemSelected.

Always try and create a separate thread to do expensive tasks so your UI thread can keep the user happy. Also, look for ways to optimize what you’re trying to do in that method. For instance, instead of swapping out resources to reflect a UI update, make a stateful skin.

SWFAddress with SWFObject gotcha’s

So a couple of things I’ve run into while using both SWFAddress and SWFObject. Thanks to some helpful blog posts, I found the answer to my issue was the order of my include statements.

Issue: Back/Forward isn’t dispatching SWFAddressEvent.CHANGE events. Some may be used to referring to that as the SWFAddress.onchange event. Either way, SWFAddress was working great, except for Back/Forward functionality.

Here’s what my simple embed code looked like before.

<script type=”text/javascript” src=”assets/script/SWFAddress.js”></script>

<script type=”text/javascript” src=”assets/script/swfobject.js”></script>

<script type=”text/javascript”>
window.onload = function() {
var so = new SWFObject(
“main.swf”, // source
“Main”, // id
“980”, // width
“100%”, // height
“10”, // required version
“#FFFFFF” // background color
);
so.addParam(“allowScriptAccess”, “always”);
so.addParam(“wmode”, “opaque”);
so.addParam(“FlashVars”, “language=en_US”);
so.write(“appContainer”);
}

</script>

And here’s the version with Back/Forward working!

<script type=”text/javascript” src=”assets/script/swfobject.js”></script>

<script type=”text/javascript” src=”assets/script/SWFAddress.js”></script>

<script type=”text/javascript”>
window.onload = function() {
var so = new SWFObject(
“main.swf”, // source
“Main”, // id
“980”, // width
“100%”, // height
“10”, // required version
“#FFFFFF” // background color
);
so.addParam(“allowScriptAccess”, “always”);
so.addParam(“wmode”, “opaque”);
so.addParam(“FlashVars”, “language=en_US”);
so.write(“appContainer”);
}

</script>

See a difference? The swfobject include statement is BEFORE the swfaddress include. Yes, it was really that easy. Thanks to NOBIEN for figuring out this simple fix. If you are looking in the error console trying to find a javascript error, it doesn’t happen. That non-error is the tricky part in this gotcha. It’s very difficult to debug a problem when you have no idea what the problem is.

This same problem will also arise if there is not an ID set for your content in SWFObject.

Blueprint – Another plugin for Flex 3/Flash Builder 4

It’s pretty cool functionality inside of eclipse. It keeps you from having to google your way through blog posts. 😀

Install it the same way that you would any eclipse plugin.

Here is Adobe’s explanation of it.

With Blueprint, Flex and Flash developers can now query for sample code just as easily as they use auto-complete. Blueprint brings the power of the entire Web inside of the Flex Builder 3 Development environment and provides sample-centered search results that allow the user to quickly look through many different examples from many different websites including documentation, blogs, and forums.

The Blueprint preview is prerelease software that is not supported by Adobe and may contain bugs. We welcome your feedback, so please use the feedback link below to request features, make comments and report problems. Please also note that this is a research project and there is no assurance that there will be a shipping version of Blueprint.

enjoy!