Jersey client in android with protocol buffer - android

I would like to create a Jersey client in Android using protocol buffer.
I am using the following libraries:
jersey-client-1.8.jar
jersey-core-1.8.jar
protobuf-java-2.4.0a.jar
The code I have written:
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
BaseRestClient client = BaseRestClient.create("", "");
HTTPBasicAuthFilter authenticationFilter =
new HTTPBasicAuthFilter(username, password);
client.addFilter(authenticationFilter);
..........
..........
WebResource webResourceGetMea = client.resource(url);
webResourceGetMea = webResourceGetMea.path("/accounts").path("/login");
ClientResponse responseGetMea = webResourceGetMea.type("application/x-protobuf").get(ClientResponse.class);
The above code is running successfully as Java main() application but when I am running it on Android the responseGetMea() object is null (last line of code).
I am using the "application/x-protobuf" because in such way it was defined on server side.
I have added the INTERNET permission in my Android application.
I also checked the URL from Android browser and when I click it, it prompts me to input the user name and the password(the expected behaviour).
I really appreciate any help.
Regards,
kalgik

An addition... When trying to POST with the version of Buscador at the previous link it complained with some errors. The new version of Buscador that works for POSTing is the following,
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import com.sun.jersey.spi.service.ServiceFinder;
import com.sun.jersey.spi.service.ServiceFinder.DefaultServiceIteratorProvider;
import com.sun.jersey.spi.service.ServiceFinder.ServiceIteratorProvider;
public class Buscador<T> extends ServiceIteratorProvider<T>
{
private static final HashMap<String, String[]> SERVICES = new HashMap<String, String[]>();
private static final String[] com_sun_jersey_spi_HeaderDelegateProvider = new String[] {
"com.sun.jersey.core.impl.provider.header.LocaleProvider",
"com.sun.jersey.core.impl.provider.header.EntityTagProvider",
"com.sun.jersey.core.impl.provider.header.MediaTypeProvider",
"com.sun.jersey.core.impl.provider.header.CacheControlProvider",
"com.sun.jersey.core.impl.provider.header.NewCookieProvider",
"com.sun.jersey.core.impl.provider.header.CookieProvider",
"com.sun.jersey.core.impl.provider.header.URIProvider",
"com.sun.jersey.core.impl.provider.header.DateProvider",
"com.sun.jersey.core.impl.provider.header.StringProvider"
};
private static final String[] com_sun_jersey_spi_inject_InjectableProvider = new String[] {
"com.sun.jersey.core.impl.provider.xml.SAXParserContextProvider",
"com.sun.jersey.core.impl.provider.xml.XMLStreamReaderContextProvider",
"com.sun.jersey.core.impl.provider.xml.DocumentBuilderFactoryProvider",
"com.sun.jersey.core.impl.provider.xml.TransformerFactoryProvider"
};
private static final String[] javax_ws_rs_ext_MessageBodyReader = new String[] {
"com.sun.jersey.core.impl.provider.entity.StringProvider",
"com.sun.jersey.core.impl.provider.entity.ByteArrayProvider",
"com.sun.jersey.core.impl.provider.entity.FileProvider",
"com.sun.jersey.core.impl.provider.entity.InputStreamProvider",
"com.sun.jersey.core.impl.provider.entity.DataSourceProvider",
"com.sun.jersey.core.impl.provider.entity.RenderedImageProvider",
"com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider",
"com.sun.jersey.core.impl.provider.entity.FormProvider",
"com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.ReaderProvider",
"com.sun.jersey.core.impl.provider.entity.DocumentProvider",
"com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader",
"com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader",
"com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader",
"com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General",
"com.sun.jersey.core.impl.provider.entity.EntityHolderReader"
};
private static final String[] javax_ws_rs_ext_MessageBodyWriter = new String[] {
"com.sun.jersey.core.impl.provider.entity.StringProvider",
"com.sun.jersey.core.impl.provider.entity.ByteArrayProvider",
"com.sun.jersey.core.impl.provider.entity.FileProvider",
"com.sun.jersey.core.impl.provider.entity.InputStreamProvider",
"com.sun.jersey.core.impl.provider.entity.DataSourceProvider",
"com.sun.jersey.core.impl.provider.entity.RenderedImageProvider",
"com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider",
"com.sun.jersey.core.impl.provider.entity.FormProvider",
"com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text",
"com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General",
"com.sun.jersey.core.impl.provider.entity.ReaderProvider",
"com.sun.jersey.core.impl.provider.entity.DocumentProvider",
"com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider",
"com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter"
};
static
{
SERVICES.put("com.sun.jersey.spi.HeaderDelegateProvider",
com_sun_jersey_spi_HeaderDelegateProvider);
SERVICES.put("com.sun.jersey.spi.inject.InjectableProvider",
com_sun_jersey_spi_inject_InjectableProvider);
SERVICES.put("javax.ws.rs.ext.MessageBodyReader", javax_ws_rs_ext_MessageBodyReader);
SERVICES.put("javax.ws.rs.ext.MessageBodyWriter", javax_ws_rs_ext_MessageBodyWriter);
}
DefaultServiceIteratorProvider defaultServiceIteratorProvider = new ServiceFinder.DefaultServiceIteratorProvider();
#SuppressWarnings("unchecked")
#Override
public Iterator<Class<T>> createClassIterator(Class<T> service, String serviceName,
ClassLoader loader, boolean ignoreOnClassNotFound)
{
String[] classesNames = SERVICES.get(serviceName);
System.out.println("!!!!!!!!!!!! serviceName: " + serviceName + " !!!!!!!!!!!!!!!!!!!");
if(classesNames==null)
{
return defaultServiceIteratorProvider.createClassIterator(service, serviceName, loader, ignoreOnClassNotFound);
}
int length = classesNames.length;
ArrayList<Class<T>> classes = new ArrayList<Class<T>>(length);
for (int i = 0; i < length; i++)
{
try
{
classes.add((Class<T>) Class.forName(classesNames[i]));
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
//return null;
return classes.iterator();
}
#Override
public Iterator<T> createIterator(Class<T> service, String serviceName, ClassLoader loader,
boolean ignoreOnClassNotFound)
{
String[] classesNames = SERVICES.get(serviceName);
int length = classesNames.length;
ArrayList<T> classes = new ArrayList<T>(length);
for (int i = 0; i < length; i++)
{
try
{
classes.add(service.cast(Class.forName(classesNames[i]).newInstance()));
} catch (IllegalAccessException e)
{
e.printStackTrace();
} catch (InstantiationException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
return classes.iterator();
}
}

I employed the solution offered at,
java.lang.NullPointerException on Android
as proposed by
Lucas Ventura, Aug 25, 2010; 9:15am
and it worked like a charm.
[EDIT]
Well, small comment/correction. Running in an HTC phone, caused the app to destroy/create when i minimised (not sure if this is normal) and re-opened. The solution proposed mandates that the Jersey client object and the ServiceFinder setting should occur in a static context. This should give a clue,
private static final BaseRestClient client;
static {
client = BaseRestClient.create("", ""); // just a helper class
ServiceFinder.setIteratorProvider(new Buscador());
}
Otherwise, the class loading fix complains in a rather strange way. Hope this helps someone...
Cheers!

Related

How to use Firebase with the Android universal music player?

Here is the Google sample app. It's set up to pull metadata from a URL with a JSON. I would like to know how to have Firebase be my source.
Here is my attempt in changing the RemoteJSONSource class:
package com.mm.android.uamp.model;
import android.support.v4.media.MediaMetadataCompat;
import android.util.Log;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.mm.android.uamp.utils.LogHelper;
import java.util.ArrayList;
import java.util.Iterator;
public class RemoteJSONSource implements MusicProviderSource {
private static final String TAG = LogHelper.makeLogTag(RemoteJSONSource.class);
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mMusic = mRootRef.child("music");
ArrayList<MediaMetadataCompat> tracksFromFB = new ArrayList<>();
public void buildFromFirebase(){
mMusic.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot music : dataSnapshot.getChildren()){
String title = music.child("title").getValue(String.class);
String album = music.child("album").getValue(String.class);
String artist = music.child("artist").getValue(String.class);
String genre = music.child("genre").getValue(String.class);
String source = music.child("source").getValue(String.class);
String id = String.valueOf(source.hashCode());
String iconUrl = music.child("image").getValue(String.class);
int trackNumber = music.child("trackNumber").getValue(Integer.class);
int totalTrackCount = music.child("totalTrackCount").getValue(Integer.class);
int duration = music.child("duration").getValue(Integer.class);
MediaMetadataCompat theMetadataFB = new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, id)
.putString(MusicProviderSource.CUSTOM_METADATA_TRACK_SOURCE, source)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, duration)
.putString(MediaMetadataCompat.METADATA_KEY_GENRE, genre)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, iconUrl)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, trackNumber)
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, totalTrackCount)
.build();
tracksFromFB.add(theMetadataFB);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
}
#Override
public Iterator<MediaMetadataCompat> iterator() {
buildFromFirebase();
ArrayList<MediaMetadataCompat> tracksFB = tracksFromFB;
return tracksFB.iterator();
}
}
The firebase onDataChange is asynchronous so I think it hasn't finished pulling the data yet before the iterator method returns tracksFB.iterator cause tracksFB array is null. Weird thing is when I run in debug mode with a line break on
ArrayList tracksFB = tracksFromFB;
It works. From my research I think I need a callback or some type of pausing task, but I just cant figure it out.
Possible relevant code connected to the iterator method
public interface MusicProviderSource {
String CUSTOM_METADATA_TRACK_SOURCE = "__SOURCE__";
Iterator<MediaMetadataCompat> iterator();
}
next
public class MusicProvider {
private static final String TAG = LogHelper.makeLogTag(MusicProvider.class);
private MusicProviderSource mSource;
private ConcurrentMap<String, List<MediaMetadataCompat>> mMusicListByGenre;
private final ConcurrentMap<String, MutableMediaMetadata> mMusicListById;
private final Set<String> mFavoriteTracks;
enum State {
NON_INITIALIZED, INITIALIZING, INITIALIZED
}
private volatile State mCurrentState = State.NON_INITIALIZED;
public interface Callback {
void onMusicCatalogReady(boolean success);
}
public MusicProvider() {
this(new RemoteJSONSource());
}
public MusicProvider(MusicProviderSource source) {
mSource = source;
mMusicListByGenre = new ConcurrentHashMap<>();
mMusicListById = new ConcurrentHashMap<>();
mFavoriteTracks = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
}
public Iterable<String> getGenres() {
if (mCurrentState != State.INITIALIZED) {
return Collections.emptyList();
}
return mMusicListByGenre.keySet();
}
/**
* Get an iterator over a shuffled collection of all songs
*/
public Iterable<MediaMetadataCompat> getShuffledMusic() {
if (mCurrentState != State.INITIALIZED) {
return Collections.emptyList();
}
List<MediaMetadataCompat> shuffled = new ArrayList<>(mMusicListById.size());
for (MutableMediaMetadata mutableMetadata: mMusicListById.values()) {
shuffled.add(mutableMetadata.metadata);
}
Collections.shuffle(shuffled);
return shuffled;
}
/**
* Get music tracks of the given genre
*
*/
public Iterable<MediaMetadataCompat> getMusicsByGenre(String genre) {
if (mCurrentState != State.INITIALIZED || !mMusicListByGenre.containsKey(genre)) {
return Collections.emptyList();
}
return mMusicListByGenre.get(genre);
}
}
Also the musicService.java in the link above might be relevant. PLEASE help!
There are two ways I can think to do this, but I'm not familiar enough with Firebase to provide working code.
The sample executes iterator() in an AsyncTask, expecting it to block until it can provide a response. So the first, and probably easiest, way to fix it would be to cause iterator() to wait on the data being loaded, or it failing to load. This could be a spinlock or something like wait/notify.
if (!dataloaded) {
try {
wait();
} catch (InterruptedException e) {}
}
ArrayList<MediaMetadataCompat> tracksFB = tracksFromFB;
return tracksFB.iterator();
I'd call buildFromFirebase(); in the constructor though, rather than waiting.
The second option would be to refactor UAMP to have it load the catalog asynchronously. This would be a lot more work, but it may result in a better design in the long run.

Why is it not possible to loop a call execute to get multiple responses inside my IntentService via Retrofit?

Why is it not possible to loop a call execute to get multiple responses inside my IntentService via Retrofit?
Please see my code:
public class UpdateAgendaService extends IntentService {
public static final int STATUS_RUNNING = 0;
public static final int STATUS_FINISHED = 1;
public static final int STATUS_ERROR = 2;
private Agenda agenda;
public UpdateAgendaService() {
super(UpdateAgendaService.class.getName());
}
#Override
protected void onHandleIntent(Intent intent) {
final ResultReceiver receiver = intent.getParcelableExtra("receiver");
String[] dateWeek = intent.getStringArrayExtra("dateWeek");
if (dateWeek != null) {
receiver.send(STATUS_RUNNING, Bundle.EMPTY);
Bundle bundle = new Bundle();
try {
//Why is this not possible?
List<Agenda> agendaList = getAgendaList(dateWeek);
receiver.send(STATUS_FINISHED, bundle);
}
} catch (Exception e) {
/* Sending error message back to activity */
bundle.putString(Intent.EXTRA_TEXT, e.toString());
receiver.send(STATUS_ERROR, bundle);
}
}
Log.d(Utilities.TAG, "Service Stopping!");
this.stopSelf();
}
private List<Agenda> getAgendaList(String[] upcomingWeekdates){
List<Agenda> agendaList = null;
for (int i = 0; i < upcomingWeekdates.length; i++) {
String weekDay = upcomingWeekdates[i];
agendaList.add(getAgenda(weekDay));
}
return agendaList;
}
private Agenda getAgenda(String date) {
Agenda agenda = null;
ApiService apiService = new QardioApi().getApiService();
Call<Agenda> call = apiService.getAgenda(date);
try {
agenda = call.execute().body();
} catch (IOException e) {
e.printStackTrace();
}
return agenda;
}
}
So the situation is that I have an API which has a url: http//:myapi.com/[date] which when called via retrofit gives me a JSON response of the Agenda(Events) for that specific day. What I want to do is to show the agenda(events) for the upcoming week, that is why I did it via loop given a String array of dates for the upcoming week. Imagine kind of like the Eventbrite app.
What I am doing wrong? I read somewhere that I should do this via JobQueue/Eventbus, should I be doing that? But I am a bit hesitant because I don't want to be using any more third party libraries. However, if that is the last case scenario I will probably just go with that then.
Nevermind guys. That was because of a very stupid mistake i made.
I just changed:
List<Agenda> agendaList = null;
to
List<Agenda> agendaList = new ArrayList<>();

Do ORMLite persisters work in Android?

Do custom persisters work on Android? I was trying to write one for an entity, and was having no luck in having it run when the entity gets written by the DAO. So, I tried to use the "MyDatePersister" from the examples and I am not able to get that working either.
The persister is nearly identical to the example one -> https://github.com/j256/ormlite-jdbc/blob/master/src/test/java/com/j256/ormlite/examples/datapersister/MyDatePersister.java
In my entity, I have
#DatabaseTable
public class ClickCount implements Serializable {
// other declarations
#DatabaseField(columnName = DATE_FIELD_NAME, persisterClass = MyDatePersister.class)
private Date lastClickDate;
// more code
}
Here is a link to the whole project in Bitbucket -> https://bitbucket.org/adstro/android-sandbox. It's basically one of the ORMLite Android examples with the custom persister example added.
Any feedback would be greatly appreciated.
Thanks
First off, what is the error result you're getting?
I got my custom persister to work just fine, though I didn't try to extend the DateType. Below is a JSONArrayPersister I found the need for. The confusing part is in the naming of the methods, but once they're setup properly, it should be ok.
package com.example.acme.persister;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.SqlType;
import com.j256.ormlite.field.types.BaseDataType;
import com.j256.ormlite.support.DatabaseResults;
import org.json.JSONArray;
import org.json.JSONException;
import java.sql.SQLException;
public class JSONArrayPersister extends BaseDataType {
public static int DEFAULT_WIDTH = 1024;
private static final JSONArrayPersister singleTon = new JSONArrayPersister();
public static JSONArrayPersister getSingleton() {
return singleTon;
}
private JSONArrayPersister() {
super(SqlType.STRING, new Class<?>[] { String.class });
}
protected JSONArrayPersister(SqlType sqlType, Class<?>[] classes) {
super(sqlType, classes);
}
#Override
public Object parseDefaultString(FieldType fieldType, String defaultStr) {
try {
return new JSONArray(defaultStr);
} catch (JSONException ex)
{
return new JSONArray();
}
}
#Override
public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException {
try {
return new JSONArray( results.getString(columnPos) );
} catch (JSONException ex)
{
return new JSONArray();
}
}
#Override
public Object resultStringToJava(FieldType fieldType, String stringValue, int columnPos) throws SQLException {
return parseDefaultString(fieldType, stringValue);
}
#Override
public int getDefaultWidth() {
return DEFAULT_WIDTH;
}
}
Then in your entity:
#DatabaseField(persisterClass = JSONArrayPersister.class)
private JSONArray something;

Android WebView -> Display WebArchive

Android's WebView has this saveWebArchive method since API level 11: http://developer.android.com/.
It can save entire websites as webarchives, which is great! But how do I get the downloaded contents back into a webview? I tried
webview.loadUrl(Uri.fromFile(mywebarchivefile));
But that only displays xml on the screen.
Update Feb. 21, 2014
My answer posted below does not apply to web archive files saved under Android 4.4 KitKat and newer. The saveWebArchive() method of WebView under Android 4.4 "KitKat" (and probably newer versions too) does not save the web archive in XML code that this reader code posted below. Instead it saves pages in MHT (MHTML) format. It is easy to read back the .mht files - just use:
webView.loadUrl("file:///my_dir/mySavedWebPage.mht");
That's all, much easier than the previous method, and compatible with other platforms.
Previously posted
I needed it myself, and everywhere I searched, there were unanswered questions like this. So I had to work it out myself. Below is my little WebArchiveReader class and sample code on how to use it. Please note that despite the Android docs declaring that shouldInterceptRequest() was added to WebViewClient in API11 (Honeycomb), this code works and was tested successfully in Android emulators down to API8 (Froyo). Below is all the code that's needed, I also uploaded the full project to GitHub repository at https://github.com/gregko/WebArchiveReader
File WebArchiveReader.java:
package com.hyperionics.war_test;
import android.util.Base64;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
public abstract class WebArchiveReader {
private Document myDoc = null;
private static boolean myLoadingArchive = false;
private WebView myWebView = null;
private ArrayList<String> urlList = new ArrayList<String>();
private ArrayList<Element> urlNodes = new ArrayList<Element>();
abstract void onFinished(WebView webView);
public boolean readWebArchive(InputStream is) {
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
myDoc = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
try {
myDoc = builder.parse(is);
NodeList nl = myDoc.getElementsByTagName("url");
for (int i = 0; i < nl.getLength(); i++) {
Node nd = nl.item(i);
if(nd instanceof Element) {
Element el = (Element) nd;
// siblings of el (url) are: mimeType, textEncoding, frameName, data
NodeList nodes = el.getChildNodes();
for (int j = 0; j < nodes.getLength(); j++) {
Node node = nodes.item(j);
if (node instanceof Text) {
String dt = ((Text)node).getData();
byte[] b = Base64.decode(dt, Base64.DEFAULT);
dt = new String(b);
urlList.add(dt);
urlNodes.add((Element) el.getParentNode());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
myDoc = null;
}
return myDoc != null;
}
private byte [] getElBytes(Element el, String childName) {
try {
Node kid = el.getFirstChild();
while (kid != null) {
if (childName.equals(kid.getNodeName())) {
Node nn = kid.getFirstChild();
if (nn instanceof Text) {
String dt = ((Text)nn).getData();
return Base64.decode(dt, Base64.DEFAULT);
}
}
kid = kid.getNextSibling();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public boolean loadToWebView(WebView v) {
myWebView = v;
v.setWebViewClient(new WebClient());
WebSettings webSettings = v.getSettings();
webSettings.setDefaultTextEncodingName("UTF-8");
myLoadingArchive = true;
try {
// Find the first ArchiveResource in myDoc, should be <ArchiveResource>
Element ar = (Element) myDoc.getDocumentElement().getFirstChild().getFirstChild();
byte b[] = getElBytes(ar, "data");
// Find out the web page charset encoding
String charset = null;
String topHtml = new String(b).toLowerCase();
int n1 = topHtml.indexOf("<meta http-equiv=\"content-type\"");
if (n1 > -1) {
int n2 = topHtml.indexOf('>', n1);
if (n2 > -1) {
String tag = topHtml.substring(n1, n2);
n1 = tag.indexOf("charset");
if (n1 > -1) {
tag = tag.substring(n1);
n1 = tag.indexOf('=');
if (n1 > -1) {
tag = tag.substring(n1+1);
tag = tag.trim();
n1 = tag.indexOf('\"');
if (n1 < 0)
n1 = tag.indexOf('\'');
if (n1 > -1) {
charset = tag.substring(0, n1).trim();
}
}
}
}
}
if (charset != null)
topHtml = new String(b, charset);
else
topHtml = new String(b);
String baseUrl = new String(getElBytes(ar, "url"));
v.loadDataWithBaseURL(baseUrl, topHtml, "text/html", "UTF-8", null);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private class WebClient extends WebViewClient {
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (!myLoadingArchive)
return null;
int n = urlList.indexOf(url);
if (n < 0)
return null;
Element parentEl = urlNodes.get(n);
byte [] b = getElBytes(parentEl, "mimeType");
String mimeType = b == null ? "text/html" : new String(b);
b = getElBytes(parentEl, "textEncoding");
String encoding = b == null ? "UTF-8" : new String(b);
b = getElBytes(parentEl, "data");
return new WebResourceResponse(mimeType, encoding, new ByteArrayInputStream(b));
}
#Override
public void onPageFinished(WebView view, String url)
{
// our WebClient is no longer needed in view
view.setWebViewClient(null);
myLoadingArchive = false;
onFinished(myWebView);
}
}
}
Here is how to use this class, sample MyActivity.java class:
package com.hyperionics.war_test;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.io.InputStream;
public class MyActivity extends Activity {
// Sample WebViewClient in case it was needed...
// See continueWhenLoaded() sample function for the best place to set it on our webView
private class MyWebClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url)
{
Lt.d("Web page loaded: " + url);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView webView = (WebView) findViewById(R.id.webView);
try {
InputStream is = getAssets().open("TestHtmlArchive.xml");
WebArchiveReader wr = new WebArchiveReader() {
void onFinished(WebView v) {
// we are notified here when the page is fully loaded.
continueWhenLoaded(v);
}
};
// To read from a file instead of an asset, use:
// FileInputStream is = new FileInputStream(fileName);
if (wr.readWebArchive(is)) {
wr.loadToWebView(webView);
}
} catch (IOException e) {
e.printStackTrace();
}
}
void continueWhenLoaded(WebView webView) {
Lt.d("Page from WebArchive fully loaded.");
// If you need to set your own WebViewClient, do it here,
// after the WebArchive was fully loaded:
webView.setWebViewClient(new MyWebClient());
// Any other code we need to execute after loading a page from a WebArchive...
}
}
To make things complete, here is my little Lt.java class for debug output:
package com.hyperionics.war_test;
import android.util.Log;
public class Lt {
private static String myTag = "war_test";
private Lt() {}
static void setTag(String tag) { myTag = tag; }
public static void d(String msg) {
// Uncomment line below to turn on debug output
Log.d(myTag, msg == null ? "(null)" : msg);
}
public static void df(String msg) {
// Forced output, do not comment out - for exceptions etc.
Log.d(myTag, msg == null ? "(null)" : msg);
}
}
Hope this is helpful.
Update July 19, 2013
Some web pages don't have meta tag specifying text encoding, and then the code we show above does not display the characters correctly. In the GitHub version of this code I now added charset detection algorithm, which guesses the encoding in such cases. Again, see https://github.com/gregko/WebArchiveReader
Greg
I've found an undocumented way of reading saved webarchive. Just do:
String raw_data = (read the mywebarchivefile as a string)
and then call
webview.loadDataWithBaseURL(mywebarchivefile, raw_data, "application/x-webarchive-xml", "UTF-8", null);
The reference:
http://androidxref.com/4.0.4/xref/external/webkit/Source/WebCore/loader/archive/ArchiveFactory.cpp
Available from Android 3.0, api level 11.

Consume WSDL to implement in Android ListView

I try to get the data from Web Service that I build with JAX-WS, WSDL and I want to implement in Android ListView.
This is my code in web service that I build on Netbeans.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package in.figures.on.mobile;
import db.koneksi.dbKoneksi;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import org.json.simple.JSONValue;
/**
*
* #author Setyadi
*/
#WebService()
public class AksesData {
/**
* Web service operation
*/
#WebMethod(operationName = "Lokasiku")
public String Lokasiku(
#WebParam(name = "lon") String lon,
#WebParam(name = "lat") String lat) {
//TODO write your implementation code here:
dbKoneksi con = new dbKoneksi();
Statement statement;
String sql = "SELECT desa "
+ "FROM dki "
+ "WHERE ST_Within(ST_SetSRID(ST_MakePoint("+lon+","+lat+"),0),geom);";
ResultSet hasil;
String desa = null;
try{
statement = con.getConnection().createStatement();
hasil = statement.executeQuery(sql);
hasil.next();
desa = hasil.getString(1);
}
catch(Exception e){
desa = "desa_thegagals";
}
finally{
}
if (con != null) {
return desa;
}
else {
return "lokasiku_thegagals";
}
}
/**
* Web service operation
*/
#WebMethod(operationName = "Kategori")
public String Kategori() {
//TODO write your implementation code here:
dbKoneksi con = new dbKoneksi();
Statement statement;
Properties properties;
List list = new ArrayList();
String sql = "SELECT kategori FROM kategori ";
ResultSet hasil;
String kategori = null;
try{
statement = con.getConnection().createStatement();
hasil = statement.executeQuery(sql);
while (hasil.next()) {
properties = new Properties();
properties.put("kategori", hasil.getString(1));
list.add(properties);
}
kategori = JSONValue.toJSONString(list);
}
catch(Exception e){
}
return kategori;
}
}
Does anybody want to help me, at least give me a tutorial about this.
Thanks in advance
Android doesn't provide any support for SOAP web services. They prefer we useRESTful web services with XML or JSON. however there are a few SOAP libraries out there. KSOAP is very popular, I personally have had issues with it. http://ksoap2.sourceforge.net/
Another suggestion is icesoap. it is a very simple library to use and understand, it worked like a charm for me.
http://code.google.com/p/icesoap/
For return data in 2D array
just get the data and convert it into String.
Then store it in Array
rs = s.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
colCount = rsmd.getColumnCount();
String[][] result;
result = new String[size][rsmd.getColumnCount()];
int j=0;
while(rs.next())
{
for (int i = 1; i <= colCount; i++)
{
Object value=null;
if(!rsmd.getColumnTypeName(i).matches("varchar"))
{
if(rsmd.getColumnTypeName(i).matches("decimal"))
value=(Object)rs.getDouble(i);
else
value=(Object)rs.getObject(i);
}
else
{
value = (Object)rs.getString(i);
}
if(value!=null)
{
result[j][i-1]=value.toString();
}
else
{
result[j][i-1]="--";
}
}j++;
}
}
catch (SQLException | ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
and In android phone toy need to get that array and convert it into appropriate data type.
If you going to display it then you can display as it is. No need to convert into its original data type.

Categories

Resources