Unity Android Get Google Play Advertising ID - java

I'm attempting to get the google play advertising ID in Unity but it doesn't seem to be working at all.
Here's the code I'm using that I've found in a couple SO's like this one:
AndroidJavaClass up = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject> ("currentActivity");
AndroidJavaClass client = new AndroidJavaClass ("com.google.android.gms.ads.identifier.AdvertisingIdClient");
AndroidJavaObject adInfo = client.CallStatic<AndroidJavaObject> ("getAdvertisingIdInfo",currentActivity);
advertisingID = adInfo.Call<string> ("getId").ToString();
using(AndroidJavaClass pluginClass = new AndroidJavaClass("example.com.Toast")) {
if(pluginClass != null) {
toastClass = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() => {
toastClass.Call("toastMessage", advertisingID);
}));
}
}
I have to do this on an actual device and haven't found a good way to actually log anything save a Toast message, which doesn't display anything here. But if I do this (which gets the android device ID) the toast displays just fine.
AndroidJavaClass up = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = up.GetStatic<AndroidJavaObject> ("currentActivity");
AndroidJavaObject contentResolver = currentActivity.Call<AndroidJavaObject> ("getContentResolver");
AndroidJavaClass secure = new AndroidJavaClass ("android.provider.Settings$Secure");
string android_id = secure.CallStatic<string> ("getString", contentResolver, "android_id");
Any idea what I should be doing to get the Google Play Advertising ID?
I've also tried doing it within the jar code itself natively like this:
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
AdvertisingIdClient.Info idInfo = null;
try {
idInfo = AdvertisingIdClient.getAdvertisingIdInfo(ToastCLass.getInstance().context);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String advertId = null;
try{
advertId = idInfo.getId();
}catch (NullPointerException e){
e.printStackTrace();
}
return advertId;
}
#Override
protected void onPostExecute(String advertId) {
Toast.makeText(ToastClass.getInstance().context, advertId, Toast.LENGTH_LONG).show();
}
};
task.execute();
But that just causes an error on my app when it runs (I think because it's trying to run the AsyncTask on the UI thread?). Again hard, as I haven't really found a way to display the logs/errors.
It seems if I run my app on an emulator I can get to a log, which does help with logging out the info.

I know this answer is a bit late, but this may be helpful for someone who is facing this issue.
First of all the answer given by Tom is correct, it works. But the reason why this error occurs is, when we add aar file of a package, we are not including all the dependencies it has. You can actually do that by checking the pom file.
So in here, to avoid this error, you can just add play-services-ads-identifier-16.0.0.aar package along with play-service-ads.
You can find this package in here

I ended up writing a custom class to access this, since the error was:
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.ads.identifier.AdvertisingIdClient"
Here's the class I wrote:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;
import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
public final class AdvertisingIdClientInfo {
public static final class AdInfo {
private final String advertisingId;
private final boolean limitAdTrackingEnabled;
AdInfo(String advertisingId, boolean limitAdTrackingEnabled) {
this.advertisingId = advertisingId;
this.limitAdTrackingEnabled = limitAdTrackingEnabled;
}
public String getId() {
return this.advertisingId;
}
public boolean isLimitAdTrackingEnabled() {
return this.limitAdTrackingEnabled;
}
}
public static AdInfo getAdvertisingIdInfo(Context context) throws Exception {
if(Looper.myLooper() == Looper.getMainLooper()) throw new IllegalStateException("Cannot be called from the main thread");
try { PackageManager pm = context.getPackageManager(); pm.getPackageInfo("com.android.vending", 0); }
catch (Exception e) { throw e; }
AdvertisingConnection connection = new AdvertisingConnection();
Intent intent = new Intent("com.google.android.gms.ads.identifier.service.START");
intent.setPackage("com.google.android.gms");
if(context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
try {
AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder());
AdInfo adInfo = new AdInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled(true));
return adInfo;
} catch (Exception exception) {
throw exception;
} finally {
context.unbindService(connection);
}
}
throw new IOException("Google Play connection failed");
}
private static final class AdvertisingConnection implements ServiceConnection {
boolean retrieved = false;
private final LinkedBlockingQueue<IBinder> queue = new LinkedBlockingQueue<IBinder>(1);
public void onServiceConnected(ComponentName name, IBinder service) {
try { this.queue.put(service); }
catch (InterruptedException localInterruptedException){}
}
public void onServiceDisconnected(ComponentName name){}
public IBinder getBinder() throws InterruptedException {
if (this.retrieved) throw new IllegalStateException();
this.retrieved = true;
return (IBinder)this.queue.take();
}
}
private static final class AdvertisingInterface implements IInterface {
private IBinder binder;
public AdvertisingInterface(IBinder pBinder) {
binder = pBinder;
}
public IBinder asBinder() {
return binder;
}
public String getId() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
String id;
try {
data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");
binder.transact(1, data, reply, 0);
reply.readException();
id = reply.readString();
} finally {
reply.recycle();
data.recycle();
}
return id;
}
public boolean isLimitAdTrackingEnabled(boolean paramBoolean) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
boolean limitAdTracking;
try {
data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");
data.writeInt(paramBoolean ? 1 : 0);
binder.transact(2, data, reply, 0);
reply.readException();
limitAdTracking = 0 != reply.readInt();
} finally {
reply.recycle();
data.recycle();
}
return limitAdTracking;
}
}
}
And then accessing it:
public void methodName(final Activity context) {
new Thread(new Runnable() {
public void run() {
try {
AdvertisingIdClientInfo.AdInfo adInfo = AdvertisingIdClientInfo.getAdvertisingIdInfo(context);
this._googleAdvertiserId = adInfo.getId();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Then wrapped that up in a jar, and in Unity you can call it:
if (activityContext == null) {
using(AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
}
using(AndroidJavaClass pluginClass = new AndroidJavaClass("example.com.Class")) {
if(pluginClass != null) {
className = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() => {
className.Call("methodName", activityContext);
}));
}
}

Related

How to return a value from a callback function

I want to return a String from a callback
My class which fetch date from server in a thread and i want this value in main thread as a String. I am beginner in Java.
public class InternetDate {
private final Activity activity;
private String finalDate = "";
public InternetDate(Activity activity) {
this.activity = activity;
}
public void setDateAndTimeFormat(String dateAndTimeFormat) {
mDateAndTimeFormat = dateAndTimeFormat;
}
public void getCurrentDate(OnGetDate onGetDate) {
new BackgroundTask(activity) {
#Override
public void doInBackground() {
try {
finalDate = getCurrentDateFromInternet();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
#Override
public void onPostExecute() {
try {
JSONObject jb = new JSONObject(finalDate);
String name = jb.getString("UnixTimeStamp");
onGetDate.onSuccess(name);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
} catch (JSONException e) {
}
}
}.execute();
}
private String getCurrentDateFromInternet() throws Exception {
String date_api = example.com/api;
URL url = new URL(date_api);
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(url.openStream()));
return in.readLine();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
}
}
public interface OnGetDate {
void onSuccess(String date);
}
I want this as a String. Please help me to archive this String in MainThread
private String getDate(){
String currentDate = "";
InternetDate internetDate = new InternetDate(this);
internetDate.getCurrentDate(new InternetDate.OnGetDate() {
#Override
public void onSuccess(String date) {
currentDate = date; // Null return
}
});
return currentDate;
}
You might wait for the response using a semaphore, but this kind of code is blocking by nature and leads to apps with a poor user experience, because the ui thread is blocked during the whole process
//import java.util.concurrent.*;
//[...]
private String getDate() throws TimeoutException {
final String[] result = new String[]{null};
final Semaphore sem = new Semaphore(0);
new InternetDate(this).getCurrentDate(new InternetDate.OnGetDate() {
#Override
public void onSuccess(String date) {
result[0] = date; // Null return
sem.release();
}
});
try {
if (sem.tryAcquire(10, TimeUnit.SECONDS)) {
return result[0];
} else {
throw new TimeoutException("no response after 10 seconds");
}
} catch(InterruptedException e) {
return null;
}
}
You can use Executors :
private String getDate() throws ExecutionException, InterruptedException {
// This line is non-blocking:
Future<String> future = Executors.newCachedThreadPool()
.submit(() -> new InternetDate().getCurrentDateFromInternet());
// The invocation of 'get' is blocking:
return future.get();
}
I assume getCurrentDateFromInternet returns the date in the format you want.
Your problem can be solved using a MutableLiveData object without blocking the UI thread.
Let's start assuming you have a main class named MainThread where your getDate method lives.
In this class first create the following MutableLiveData object:
private MutableLiveData<String> date = new MutableLiveData<>();
The object above will be updated with the date value as soon as it's available to your program.
Next create/update the method that'll make a call to the getDate method (which we'll keep for simplicity's sake):
private void exampleDateMethod() {
// first create an observer; in the observer you put the code that does something with the Date
date.observe(this, new Observer<String>() {
#Override
public void onChanged( String date ) {
// this is where you do something with the date, an example:
findViewById( R.id.date_view ).setText( date );
}
});
// pass the MutableLiveData to the getDate method so that its value can be updated:
getDate( date );
}
And change the getDate method to pass the Date to the MutableLiveData object:
private void getDate( MutableLiveData<String> liveDate ){
internetDate.getCurrentDate(new InternetDate.OnGetDate() {
#Override
public void onSuccess(String date) {
// set the value of the MutableLiveData object, this will notify the observer and execute the code in its onChanged method
liveData.setValue( date );
}
});
}

javac illegal character 'ufeff'

I am having a problem with my javac program in cmd, I am running Java jdk1.8.0_152 and I am getting the following errors:
C:\[My_Path]>javac -encoding UTF-8 Main.java
Main.java:1: error: illegal character: '\ufeff'
?package tanks;
^
Main.java:1: error: class, interface, or enum expected;
package tanks;
^
2 errors
I checked the file using different software (text editors) and rewrote the document, and still got the error. I do not have a '?' in the front of the document, but javac for some reason detects it out of nowhere.
Full Document: Main.Java
package tanks;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import tanks.DataBase.Numeric.NumericDB;
import tanks.DataBase.Turrent.TurrentDB;
import tanks.DataBase.User;
import tanks.DataBase.Users;
public class Main implements Runnable {
private static Main instance;
private ServerSocket ss;
private static double version = 0.1D;
public static Lobby systemUser;
public static Vector lobbys = new Vector();
private static boolean isDebug = false;
private static ControlWindow cw;
private static boolean started = false;
public static void main(string[] paramArrayOfString) throws Exception {
cw = new ControlWindow();
cw.setVisible(true);
}
private static void disposeLobbys() {
for (int i = 0; i < lobby.size(); i++) {
Bobby localLobby = (Lobby)lobbys.elementAt(i);
state = SocketProcessor.STATE_ERROR;
try {
is.close();
os.close();
s.close();
}
catch(Exception localException) {}
}
lobbys = new Vector();
}
public static void stopServer() {
if (!started) return;
GarageDataBaseParser.save();
started = false;
NumericsDB.dispose();
Battles.dispose();
disposeBobbys();
tanks.DataBase.Battle.BonusDB.dispose();
System.gc();
cw.showMessage("Server Started", "Server RU_1 Notification");
}
public static void startServer() {
try {
started = true;
NumericDB.init();
tanks.DataBase.Colormap.ColormapDB.init();
ServerSocket localServerSocket;
if (isDebug) {
localServerSocket = new ServerSocket(2845);
} else {
localServerSocket = new ServerSocket(5482);
}
new Thread(new Main(localServerSocket)).start();
cw.showMessage("Server Started!", "Server RU_1 Notification");
} catch (Exception localExeption) { cw.showMessage(localExption.getMessage(), "Server RU_1 Notification");
}
}
public Main(ServerSocket paramServerSocket) {
instance = this;
ss = paramServerSocket;
}
public void run() {
try {
while (started) {
Socket localSocket = ss.accept();
new Thread(new Starter(localSocket)).start();
}
}
catch (Exeption localExeption1) {
cw.showMessage(localExeption1.getMessage(), "Server RU_1 Notification");
}
try {
ss.close();
}
catch (Exception localExcption2) {
cw.showMessage(localException2.getMessage(), "Server RU_1 Notification");
}
ss = null;
}
private static void disposeUsers() {}
private static void initUsers() {
UserDataBaseParser.load("ServerDataBase/Users.txt");
systemUser = new Lobby(Users.getUser(0), null, null, null);
GarageDataBaseParser.load();
}
public static void removeLobby(int paramInt) {
Lobby localLobby = (Lobby)lobbys.elementAt(paramInt);
lobbys.removeElementAt(paramInt);
localLobby = null;
}
public static void removeLobby(Lobby paramLobby) {
lobbys.removeElement(paramLobby);
paramLobby = null;
}
public static void startLobby(BattleProcessor paramBattleProcessor, User paramUsers) {
Lobby localLobby = new Lobby(paramUser, s, is, os);
lobbys.addElement(localLobby);
new Thread(localLobby).start();
}
public static void startLobby(Starter paramStarter, User paramUser) {
cwlistModel.addElement(login);
Battles.check(paramUser);
Lobby localLobby = new Lobby(paramUser, s, is, os);
lobbys.addElement(localLobby);
new Thread(localLobby).start();
paramStarter = null;
}
}

Unit testing, custom Call class for retrofit2 request: Reponse has private access

When I create custom Call class I can't return Response, because Response class is final. Is there any workaround for this?
public class TestCall implements Call<PlacesResults> {
String fileType;
String getPlacesJson = "getplaces.json";
String getPlacesUpdatedJson = "getplaces_updated.json";
public TestCall(String fileType) {
this.fileType = fileType;
}
#Override
public Response execute() throws IOException {
String responseString;
InputStream is;
if (fileType.equals(getPlacesJson)) {
is = InstrumentationRegistry.getContext().getAssets().open(getPlacesJson);
} else {
is = InstrumentationRegistry.getContext().getAssets().open(getPlacesUpdatedJson);
}
PlacesResults placesResults= new Gson().fromJson(new InputStreamReader(is), PlacesResults.class);
//CAN"T DO IT
return new Response<PlacesResults>(null, placesResults, null);
}
#Override
public void enqueue(Callback callback) {
}
//default methods here
//....
}
In my unit test class I want to use it like this:
Mockito.when(mockApi.getNearbyPlaces(eq("testkey"), Matchers.anyString(), Matchers.anyInt())).thenReturn(new TestCall("getplaces.json"));
GetPlacesAction action = new GetPlacesAction(getContext().getContentResolver(), mockEventBus, mockApi, "testkey");
action.downloadPlaces();
My downloadPlaces() method look like:
public void downloadPlaces() {
Call<PlacesResults> call = api.getNearbyPlaces(webApiKey, LocationLocator.getInstance().getLastLocation(), 500);
PlacesResults jsonResponse = null;
try {
Response<PlacesResults> response = call.execute();
Timber.d("response " + response);
jsonResponse = response.body();
if (jsonResponse == null) {
throw new IllegalStateException("Response is null");
}
} catch (UnknownHostException e) {
events.sendError(EventBus.ERROR_NO_CONNECTION);
} catch (Exception e) {
events.sendError(EventBus.ERROR_NO_PLACES);
return;
}
//TODO: some database operations
}
After looking at retrofit2 Response class more thoroughly I've found out that there is a static method that do what I need. So, I simply changed this line:
return new Response<PlacesResults>(null, placesResults, null);
to:
return Response.success(placesResults);
Everything works now.

The method getApplication() is undefined for the type (my class)

I am using a global variables "GlobalVariables" in a separated class and I am try to use it in the following code but it is always gives me the error :
The method getApplication() is undefined for the type UploadPicture
I tried the following but still have error:
((GlobalVariables) this.getApplication()).set_FileUploading(false);
The qustion was already asked here but unfortunatlly all the answors didn't work with me and gave me same error! any suggestion please?
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private String mErrorMsg;
private File outFiles;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath, File file) {
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
}
#Override
protected Boolean doInBackground(Void... params) {
try {
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + outFiles.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
return 500;
}
#Override
public void onProgress(long bytes, long total) {
//publishProgress(bytes);
}
}
);
if (mRequest != null) {
mRequest.upload();
((GlobalVariables) UploadPicture.this.getApplication()).set_FileUploading(false);
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
Edit: I am adding now my "VariableGlobales" calss:
public class GlobalVariables extends Application {
private Boolean _IsIOIORunning=false;
private Boolean _FileUploading=false;
public Boolean get_IsIOIORunning()
{
return _IsIOIORunning;
}
public void set_IsIOIORunning(Boolean _IsIOIORunning)
{
this._IsIOIORunning = _IsIOIORunning;
}
public Boolean get_FileUploading()
{
return _FileUploading;
}
public void set_FileUploading(Boolean _FileUploading)
{
this._FileUploading = _FileUploading;
}
It's normal UploadPicture doesn't extend GlobalVariables but it extend AsyncTask.
That it's my "GlobalVariables "
public class AppInfo extends Application {
private static Context context;
private static String user;
public void onCreate(){
super.onCreate();
AppInfo.context = getApplicationContext();
user = null;
}
public static Context getAppContext() {return AppInfo.context;}
public static String getUser() {return user;}
public static void setUser(String user) {AppInfo.user = user;}
}
And I call it everywhere like that:
AppInfo.getUser();
Edit:
GlobalVariables should use static method and variables:
public class GlobalVariables extends Application {
private static Boolean _IsIOIORunning=false;
private static Boolean _FileUploading=false;
public static Boolean get_IsIOIORunning() {
return _IsIOIORunning;
}
public static void set_IsIOIORunning(Boolean _IsIOIORunning) {
GlobalVariables._IsIOIORunning = _IsIOIORunning;
}
public static Boolean get_FileUploading(){
return _FileUploading;
}
public static void set_FileUploading(Boolean _FileUploading){
GlobalVariables._FileUploading = _FileUploading;
}
}

How to wrap these classes into a AsyncClass and then using them?

I'm trying to put together a simple RSS reader, and found code on http://www.ibm.com/developerworks/opensource/library/x-android/
Todo so, I noticed that you can not do network operations from the main thread since Honeycomb and have a hard time wrapping this class into a working AsyncTask:
package tlib.net.rss;
import java.util.ArrayList;
import java.util.List;
import android.sax.Element;
import android.sax.EndElementListener;
import android.sax.EndTextElementListener;
import android.sax.RootElement;
import android.util.Xml;
public class SaxFeedParser extends BaseFeedParser {
public SaxFeedParser(String feedUrl) {
super(feedUrl);
}
public List<Message> parse() {
final Message currentMessage = new Message();
RootElement root = new RootElement("rss");
final List<Message> messages = new ArrayList<Message>();
Element channel = root.getChild("channel");
Element item = channel.getChild(ITEM);
item.setEndElementListener(new EndElementListener(){
public void end() {
messages.add(currentMessage.copy());
}
});
item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setTitle(body);
}
});
item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setLink(body);
}
});
item.getChild(DESCRIPTION).setEndTextElementListener(new
EndTextElementListener(){
public void end(String body) {
currentMessage.setDescription(body);
}
});
item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
public void end(String body) {
currentMessage.setDate(body);
}
});
try {
Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
return messages;
}
}
this code also calls the base-class: BaseFeedParser which i guess also has to be wrapped into a AsyncTask. the code for BaseFeedParser looks like:
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
public abstract class BaseFeedParser implements FeedParser {
// names of the XML tags
static final String CHANNEL = "channel";
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
private final URL feedUrl;
protected BaseFeedParser(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
I don't know if i'm simply dumb or having a bad day, but i don't get how this is supposted to happend. Could someone help me and my afternoon brain out to get this working?
Currently i use:
SaxFeedParser rss = new SaxFeedParser("http://www.androidster.com/android_news.rss");
messages = rss.parse();
for(Message message : messages)
{
tv.appendText(message);
}
to process the stream, how would i do if everything was done with AsyncTask?
Kind regards
Hiam
I have not tried this, but it should work.
Basically the AsyncTask will retrieve the url(s) contents, parse it and publish the parsed messages.The onProgressUpdate() is used to safely update the user interface as you please.
class ParserTask extends AsyncTask<String, List<Message>, Long> {
protected Long doInBackground(String... urls) {
if (urls == null || urls.length == 0)
return null;
for (String url : urls) {
SaxFeedParser rss = new SaxFeedParser(url);
List<Message> messages = rss.parse();
publishProgress(messages);
}
return null; //return somethingForPostExecute;
}
protected void onProgressUpdate(List<Message>... messages) {
if (messages == null || messages.length == 0)
return;
for (Message message : messages[0]) {
// tv.appendText(message);
// or call method from GUI thread (the activity)
}
}
protected void onPostExecute(Long nr) {
}
}
Then you use something like:
new ParserTask().execute("http://www.androidster.com/android_news.rss");
Or you could use multiple urls:
new ParserTask().execute(new String[]{"http://www.androidster.com/android_news.rss", "..."});

Categories