I'm trying to implementing a parallel download using a Thread, but all my unzip process should be sequentially. As is known Intent Service enqueue all pending task so in the end of all my downloads I'm trying to start a intent service. The problem is that I'm getting the following error:
05-30 11:49:10.520: E/AndroidRuntime(18790): FATAL EXCEPTION: main
05-30 11:49:10.520: E/AndroidRuntime(18790): java.lang.RuntimeException: Unable to instantiate service br.com.facilit.target.app.android.util.UnzipService: java.lang.InstantiationException: can't instantiate class br.com.facilit.target.app.android.util.UnzipService; no empty constructor
My Download Thread:
public class DownloadService implements Runnable {
Activity controller;
boolean post;
String urlParent;
String filePath;
String destinationPath;
ResultReceiver mReceiver;
String typeDownload;
MetaDados metaDado;
int index;
boolean isResuming;
File jsonFile = new File(Constants.DEST_PATH_PARENT + Constants.JSON_FILES_PATH);
File jsonTempFile;
public DownloadService(Activity controller, boolean post, String urlParent, String filePath,
String destinationPath, ResultReceiver mReceiver, String typeDownload, int index, MetaDados metaDado,
boolean isResuming) {
this.controller = controller;
this.post = post;
this.urlParent = urlParent;
this.filePath = filePath;
this.destinationPath = destinationPath;
this.mReceiver = mReceiver;
this.typeDownload = typeDownload;
this.index = index;
this.metaDado = metaDado;
this.isResuming = isResuming;
}
#Override
public void run() {
Log.d(Constants.DOWNLOAD_AND_UNZIP_SERVICE, "Começando processo de download");
// ALL DOWNLOAD PROCESS
// THEN CALL INTENT FOR UNZIP
final Intent service = new Intent(controller.getApplicationContext(), UnzipService.class);
service.putExtra("post", false);
service.putExtra("filePath", filePath);
service.putExtra("destinationPath", destinationPath);
service.putExtra("receiver", mReceiver);
service.putExtra("typeDownload", Constants.HTML);
service.putExtra("metaDado", metaDado);
service.putExtra("isResuming", false);
controller.runOnUiThread(new Runnable() {
#Override
public void run() {
controller.startService(service);
}
});
}
}
My Unzip Intent Service:
public class UnzipService extends IntentService {
public UnzipService(String name) {
super("UnzipService");
}
#Override
protected void onHandleIntent(Intent intent) {
String filePath = intent.getStringExtra("filePath");
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
Log.d("UnzipService", "Simulando descompactação de arquivo " + filePath);
} catch (InterruptedException e) {
}
}
}
}
Manifest:
<service android:name="br.com.facilit.target.app.android.util.UnzipService"/>
as the exception reports you have no empty constructor Change it in:
public UnzipService() {
super("UnzipService");
}
Related
I am building Android App which shows Withings user's activity data in my Application.
But when I am trying to call refresh_token url:
https://oauth.withings.com/account/request_token?oauth_callback=******&oauth_consumer_key=******&oauth_nonce=******&oauth_signature=CcMrI7JaI8M5tEenye3s95wx%2BZ4%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1477386344&oauth_version=1.0
Then I am getting Invalid Signature response like below:
{
"status":0,
"message":"Invalid signature :\n CcMrI7JaI8M5tEenye3s95wx+Z4= .. \n{\"oauth_callback\":\"******\",\"oauth_consumer_key\":\"ce54bd6c671546ef8f8d394c0db4bd86688289d5f7fb39f371c5ebce4d01\",\"oauth_nonce\":\"f339febe0fdf4b53b953501e45a049db\",\"oauth_signature\":\"CcMrI7JaI8M5tEenye3s95wx+Z4=\",\"oauth_signature_method\":\"HMAC-SHA1\",\"oauth_timestamp\":\"1477386344\",\"oauth_version\":\"1.0\"}\n{\"base_string\":\"GET&https%3A%2F%2Foauth.withings.com%2Faccount%2Frequest_token&oauth_callback%3D******%26oauth_consumer_key%3D******%26oauth_nonce%3Df339febe0fdf4b53b953501e45a049db%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1477386344%26oauth_version%3D1.0\"}\n{\"key\":\"******\",\"secret\":\"******\",\"callback_url\":null}"
}
First of all you can use the scribe lib
On my sample code I have an Authentication Activity that has an WebView that the user uses to verify the app. Then that Authentication Activity sends back to the MainActivity the response.
On my example I am storing locally on a DB the authenticated user to not ask every time the credentials.
Also I am sending the access token to python server that will get all data stored on Withings Cloud to save it to my Server DB and represent them on a Graph Activity. {I have removed that part}
Because of the copy paste maybe something is missing but most of the code is here
public class WithingsApi extends DefaultApi10a {
private static final String AUTHORIZATION_URL ="https://oauth.withings.com/account/authorize?oauth_token=%s";
private static final String apiKey = "API_KEY";
private static final String apiSecret = "API_SECRET";
#Override
public String getRequestTokenEndpoint() {
return "https://oauth.withings.com/account/request_token";
}
#Override
public String getAccessTokenEndpoint() {
return "https://oauth.withings.com/account/access_token";
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return String.format(getAUTHORIZATION_URL(), requestToken.getToken());
}
public static String getKey(){
return apiKey;
}
public static String getSecret(){
return apiSecret;
}
public static String getAUTHORIZATION_URL() {
return AUTHORIZATION_URL;
}
}
#SuppressLint("SetJavaScriptEnabled")
public class AuthenticationActivity extends Activity {
final String LOGTAG = "WITHINGS";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_authentication);
final WebView wvAuthorise = (WebView) findViewById(R.id.wvAuthorise);
wvAuthorise.getSettings().setJavaScriptEnabled(true);
wvAuthorise.setWebViewClient(new MyWebViewClient(wvAuthorise));
MainActivity.service = new ServiceBuilder().provider(WithingsApi.class)
.apiKey(WithingsApi.getKey())
.apiSecret(WithingsApi.getSecret())
.build();
new Thread(new Runnable() {
public void run() {
MainActivity.requestToken = MainActivity.service.getRequestToken();
final String authURL = MainActivity.service.getAuthorizationUrl(MainActivity.requestToken);
wvAuthorise.post(new Runnable() {
#Override
public void run() {
wvAuthorise.loadUrl(authURL);
}
});
}
}).start();
}
class MyWebViewClient extends WebViewClient{
WebView wvAuthorise;
MyWebViewClient(WebView wv){
wvAuthorise = wv;
}
#Override
public void onPageFinished(WebView view, String url) {
getUSERID(url);
}
}
private void getUSERID(final String url) {
try {
String divStr = "userid=";
int first = url.indexOf(divStr);
if(first!=-1){
final String userid = url.substring(first+divStr.length());
Intent intent = new Intent();
intent.putExtra("USERID",userid);
setResult(RESULT_OK,intent);
finish();
}
else
{
//...
}
} catch (Exception e) {
Log.e(LOGTAG,e.getMessage());
//...
}
}
}
public class MainActivity extends FragmentActivity {
public static OAuthService service;
public static Token requestToken;
String secret, token;
Token accessToken;
String userId = "";
private UsersDataSource datasource;
private TextView nameTV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_mainActivity = this;
nameTV = (TextView) findViewById(R.id.nameTitleTextView);
nameTV.setText("--");
getCredentials();
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == AUTHENTICATION_REQUEST) {
if (resultCode == RESULT_OK) {
Bundle extras = intent.getExtras();
if (extras != null) {
userId = extras.getString("USERID");
getAccessTokenThread.execute((Object) null);
}
}
}
}
#Override
protected void onResume() {
datasource.open();
super.onResume();
}
#Override
protected void onPause() {
datasource.close();
super.onPause();
}
private void getCredentials() {
try {
datasource = new UsersDataSource(this);
datasource.open();
List<User> users = datasource.getAllUsers();
if (users.isEmpty()) {
startAuthenticationActivity();
} else {
// TODO load all users and if isn't anyone correct
// startAuthenticationActivity
secret = users.get(0).getSecret();
token = users.get(0).getToken();
userId = users.get(0).getUserId();
Log.i(LOGTAG, "secret : " + secret);
Log.i(LOGTAG, "token : " + token);
Log.i(LOGTAG, "userId : " + userId);
try {
service = new ServiceBuilder().provider(WithingsApi.class)
.apiKey(WithingsApi.getKey())
.apiSecret(WithingsApi.getSecret()).build();
accessToken = new Token(token, secret);
loadData();
} catch (Exception ex) {
startAuthenticationActivity();
}
}
} catch (Exception ex) {
Log.e(LOGTAG, "try on create" + ex.getLocalizedMessage());
}
}
private void startAuthenticationActivity() {
Intent intent = new Intent(this,
ics.forth.withings.authentication.AuthenticationActivity.class);
startActivityForResult(intent, AUTHENTICATION_REQUEST);
}
AsyncTask<Object, Object, Object> getAccessTokenThread = new AsyncTask<Object, Object, Object>() {
#Override
protected Object doInBackground(Object... params) {
accessToken = service
.getAccessToken(requestToken, new Verifier(""));
secret = accessToken.getSecret();
token = accessToken.getToken();
return null;
}
#Override
protected void onPostExecute(Object result) {
// authentication complete send the token,secret,userid, to python
datasource.createUser(token, secret, userId);
loadData();
};
};
}
UPDATE
OAuthService class is from Scribe
Token class is from Scribe
UserDataSource class is a DB Helper Class more here
I have a regular class (SOAP.java) which I added a function to call a webservice, I have the URL and other informations in res/values/strings.xml.
My Intent Service (which is called every 2 minutes) and a Fragment of my App are using the function in SOAP.java, but I can't get access to the strings, error:
08-19 03:47:19.730 16543-17323/fr.solutis.solutis E/AndroidRuntime﹕
FATAL EXCEPTION: IntentService[EnvoieService]
Process: fr.solutis.solutis, PID: 16543
java.lang.NullPointerException
at fr.solutis.solutis.SOAP.(SOAP.java:22)
at fr.solutis.solutis.notifications.EnvoieService.onHandleIntent(EnvoieService.java:96)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
SOAP.java:
public class SOAP {
private Context context;
public SOAP(Context current){
this.context = current;
}
String NAMESPACE = context.getResources().getString(R.string.NAMESPACE);
String URL = context.getResources().getString(R.string.URL);
String SOAP_ACTION = context.getResources().getString(R.string.SOAP_ACTION);
private static String TAG = SOAP.class.getSimpleName();
public Reponse envoieDemande(String method, String xml) {
code
}
}
IntenService:
public class EnvoieService extends IntentService {
DatabaseHandler db = new DatabaseHandler(this);
public EnvoieService() {
super("EnvoieService");
}
#Override
protected void onHandleIntent(Intent intent) {
List<Demande> demandes = db.getAllDemandesRenvoie();
String TAG = EnvoieService.class.getSimpleName();
if (!(demandes.isEmpty())) {
for (Demande cn : demandes) {
...
SOAP soap = new SOAP(this);
Reponse ret = soap.envoieDemande("SendLead", xml);
}
} else {
cancelAlarm();
}
}
public void cancelAlarm() {
Intent intent = new Intent(getApplicationContext(), EnvoieReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, EnvoieReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pIntent);
}
}
Fragment:
public class DemandeGratuite extends android.support.v4.app.Fragment {
...
{
{
{
{
{
{
{
{
AsyncSoapCall task = new AsyncSoapCall();
task.execute();
getChildFragmentManager().popBackStack();
mListener.onInteraction(6);
} catch (FileNotFoundException e) {
System.err.println("FileNotFoundException: " + e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
}
}
}
);
}
private class AsyncSoapCall extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
SOAP soap = new SOAP(getContext());
Reponse ret = soap.envoieDemande("SendLead", xml);
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i(TAG, "onPostExecute");
}
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
}
}
Resources cannot be accesed from the context of a service. You must use the context of an activity or u can try to use this class
public class App extends Application {
private static Context mContext;
public static Resources getResources() {
return mContext.getResources();
}
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
}
and then use the function App.getResources().getString(your_string_id) from wherever you want
I am having a Custom View which uploading image to the server when clicked.
I get the context using getContext and use it to call start the intent service. Somehow the service didn't get started when I make a checkpoint at the onHandleIntent or onStartCommand. I have placed a reference in the manifest.
This is the code call to service in which the code was inside the Custom View which extending the ImageView:
new GraphicUtilitiesV2.SimpleImageLoadingCallback() {
#Override
public void imageAvailable(Object sender, String data) {
if (_formCOC != null && _formType != null) {
Gson gson = new Gson();
String formCOC = gson.toJson(_formCOC);
UploadAttachmentService.startActionAttachmentDeclarative
(getContext(), formCOC, _formType.getValue(), data);
}
}
});
This is my demo code of the AttachmentUploadService class :
private static final String ACTION_DECLARATIVE = "blah.Service.action.DeclarativeAttachment";
private static final String EXTRA_FORM = "blah.CERTIFI.Service.extra.Form";
private static final String EXTRA_TYPE = "blah.Service.extra.FormType";
private static final String EXTRA_DATA = "blah.Service.extra.Data";
public static void startActionAttachmentDeclarative(Context context, String form, String type, String data) {
Intent intent = new Intent(context, UploadAttachmentService.class);
intent.setAction(ACTION_DECLARATIVE);
intent.putExtra(EXTRA_FORM, form);
intent.putExtra(EXTRA_TYPE, type);
intent.putExtra(EXTRA_DATA, data);
context.startService(intent);
}
public UploadAttachmentService() {
super("UploadService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_DECLARATIVE.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_FORM);
final String param2 = intent.getStringExtra(EXTRA_DATA);
handleActionAttachmentDeclarative(param1, param2);
}
}
}
public void handleActionAttachmentDeclarative(String form, String data) {
try {
Thread.sleep(50000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
There are no error or force close as well.
This is my manifest part:
<service
android:name=".Service.UploadAttachmentService"
android:exported="false" >
</service>
The UploadAttachmentService file was stored in a Service folder.
This is my Service which does network operation. But it is throwing NetworkonMainThreadException which i understand android upper version doesn't allows network operation under main thread. Now i want to use Async Task for this purpose. I am not sure which are all code i need to add under Async Task from Service Class to actually make the code complete. Below is my Service Code :
public class NewsTickerDataService extends Service {
#Override
public void onStart(Intent aIntent, int aStartId) {
super.onStart(aIntent, aStartId);
RemoteViews _views = buildUpdatedViews(this);
ComponentName _widget =
new ComponentName(this, NewsTicker.class);
AppWidgetManager _manager =
AppWidgetManager.getInstance(this);
_manager.updateAppWidget(_widget, _views);
}
#Override
public IBinder onBind(Intent aParamIntent) {
// not supporting binding
return null;
}
private RemoteViews buildUpdatedViews(Context aContext) {
List<Story> _stories = getStories();
RemoteViews _result = new RemoteViews(
aContext.getPackageName(),
R.layout.activity_main
);
if (_stories.isEmpty()) {
_result.setTextViewText(R.id.title,
"Sadly there's nothing to read today.");
} else {
_result.setTextViewText(
R.id.title, _stories.get(0).getTitle());
}
return _result;
}
private List<Story> getStories() {
try {
URL _url = new URL("http://search.twitter.com" +
"/search.atom?q=%23uml&" +
"result_type=mixed&count=5"
);
InputStream _in = _url.openStream();
return parse(new InputSource(_in));
} catch (Exception anExc) {
Log.e("NewsTicker", anExc.getMessage(), anExc);
return new ArrayList<Story>();
}
}
private List<Story> parse(InputSource aSource)
throws Exception {
SAXParserFactory _f = SAXParserFactory.newInstance();
SAXParser _p = _f.newSAXParser();
XMLReader _r = _p.getXMLReader();
AbstractParser _h = AbstractParser.newAtomParser();
_r.setContentHandler(_h);
_r.parse(aSource);
return _h.getStories();
}
}
Async Task Code :
public class YourAsyncTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// your load work
//return myString;
}
#Override
protected void onPostExecute(String result) {
}
}
Can someone please help me to integrate Async Task into same code. Thanks
Yes, I'd suggest IntentService too!
IntentService example
public class MyService extends IntentService {
private int STOP_DOWNLOAD = false;
public static int UPDATE_PROGRESS = 0;
public MyService() {
super("myservice");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(Intent intent) {
// Network Task : download ?
// Send some data to the receiver
Bundle resultData = new Bundle();
resultData.putInt("progress", progress);
receiver.send("update", resultData);
}
private void stopDownload() {
this.STOP_DOWNLOAD = true;
// Stop the download : use this boolean into onHandleIntent
}
}
The receiver
public class MyReceiver extends ResultReceiver {
Context context;
public MyReceiver(Context mContext) {
super(handler);
context = mContext;
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == "update") {
String something = resultData.getString(MyService.SOMETHING);
}
}
}
Start the service in an Activity : startService(...)
From the onStart() of your service class make network operation
YourAsyncTask.execute(url);
Async task code
public class YourAsyncTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// your load work
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
//return myString;
}
#Override
protected void onPostExecute(String result) {
//HERE CALL YOUR PARSE METHOD
//AFTER PARSING CALL buildUpdatedViews(Context aContext , stories)
}
}
this is the class that calls my Service:
public class TicketList extends ListActivity
{
private ArrayList<Tickets> alTickets = new ArrayList<Tickets>();
private boolean listCreated = false;
private static Drawable background = null;
private Resources res;
private Tickets ticket = null;
private TicketConnector localService;
/**
* Called when the activity is first created.
*
*/
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.ticketlist);
if(!listCreated)
{
connectService();
//populateList();
res = getResources();
background = res.getDrawable(R.drawable.background);
listCreated = true;
}
TicketAdapter StatisticsAdapter = new TicketAdapter(this, alTickets);
setListAdapter(StatisticsAdapter);
}
/**
* Populates the ListView.
* This needs to be done once the Activity is created and if the menu entry refresh is hit.
*/
private void populateList()
{
try
{
String jsonString = localService.queryData(new String[] {"getTicketList"}, new String[] {"Offen"});
//String jsonString = new TicketConnector().queryData(new String[] {"getTicketList"}, new String[] {"Offen"});
JSONObject jsonObj = new JSONObject(jsonString);
JSONArray ticketArray = jsonObj.getJSONArray("tickets");
Tickets[] tickets = new Tickets[ticketArray.length()];
for (int i=0;i<ticketArray.length();i++)
{
JSONObject object = ticketArray.getJSONObject(i).getJSONObject("ticket");
ticket = new Tickets(object.getString("id"), object.getString("color"), object.getString("priority"));
alTickets.add(ticket);
}
}
catch (Exception e)
{
Log.e("DayTrader", "Exception getting JSON data", e);
}
}
private void connectService()
{
Intent intent = new Intent(getApplicationContext(), TicketConnector.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
public void getData()
{
String s = localService.queryData(new String[] {"getTicketList"}, new String[] {"Offen"});
}
ServiceConnection connection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName name, IBinder binder)
{
Toast.makeText(TicketList.this, "Service connected",Toast.LENGTH_SHORT).show();
localService = ((TicketConnector.LocalBinder)binder).getService();
Log.i("INFO", "Service bound: TicketConnector");
}
#Override
public void onServiceDisconnected(ComponentName name)
{
Toast.makeText(TicketList.this, "Service disconnected",Toast.LENGTH_SHORT).show();
localService = null;
Log.i("INFO", "Service unbound: TicketConnector");
}
};
}
And this is the service:
public class TicketConnector extends Service
{
private SharedPreferences settings = null;
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder binder = new LocalBinder();
private String username = null;
private String password = null;
private String server = null;
private String port = null;
private String urlStr = null;
private String result = null;
#Override
public void onCreate()
{
settings = CMDBSettings.getSettings(this);
username = settings.getString("username", "");
password = settings.getString("password", "");
server = settings.getString("server", "");
port = settings.getString("serverport", "");
}
#Override
public IBinder onBind(Intent intent)
{
return binder;
}
#Override
public void onDestroy()
{
}
public String queryData(String[] actions, String[] category)
{
//http://localhost:8080/MobileCMDB/TicketListener?format=json&actions=getTicketList&ticketcategory=Open
urlStr = "http://"+server+":"+port+"/MobileCMDB/TicketListener?format=";
new jsonParser().execute(actions);
return result;
}
abstract class BaseParser extends AsyncTask<String, Integer, String>
{
protected BaseParser(String format)
{
urlStr += format;
}
private String makeUrlString(String[] actions, String[] category)
{
StringBuilder sb = new StringBuilder(urlStr);
for (int i=0;i<actions.length;i++)
{
sb.append("&actions=");
sb.append(actions[i]);
sb.append("&ticketcategory=");
sb.append(category[i]);
}
return sb.toString();
}
protected InputStream getData(String[] actions, String[] category) throws Exception
{
URI uri = new URI(makeUrlString(actions, category));
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(uri);
request.addHeader("Accept-Encoding","gzip");
HttpResponse response = client.execute(request);
InputStream content = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip"))
{
content = new GZIPInputStream(content);
}
return content;
}
#Override
protected void onPostExecute(String jsonString)
{
result = jsonString;
}
}
private class jsonParser extends BaseParser
{
public jsonParser()
{
super("json");
}
#Override
protected String doInBackground(String... actions)
{
String[] category = new String[] {"Open"};
StringBuilder json = null;
try
{
json = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(getData(actions, category)));
String line = reader.readLine();
while (line != null)
{
json.append(line);
line = reader.readLine();
}
}
catch (Exception e)
{
Log.e("PrimeCMDB - Network", "Exception getting JSON data", e);
}
return json.toString();
}
}
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder
{
public TicketConnector getService()
{
return TicketConnector.this;
}
}
}
This are the two activities in the AndroidManifest.xml:
<activity
android:name=".ticket.TicketList"
android:label="#string/ticket"
/>
<service
android:name=".network.TicketConnector"
android:enabled="true"
/>
onServiceConnected is never executed. Did I miss something?
Here is the output of LogCat at verbose mode while activating the TicketList Activity:
09-28 23:22:11.420: INFO/ActivityManager(795): Starting activity: Intent { cmp=org.mw88.cmdb/.gui.TicketListActivity }
09-28 23:22:12.340: WARN/ActivityManager(795): Binding with unknown activity: android.os.BinderProxy#4410bf30
09-28 23:22:16.090: INFO/ActivityManager(795): Displayed activity org.mw88.cmdb/.gui.TicketListActivity: 4606 ms (total 4606 ms)
Thank you all for your Answers.
I found the question after searching Google for this log message:
Binding with unknown activity: android.os.BinderProxy
It seems that Android has a bug when using bindService to fill a TabSpec Activity!
The solution was pretty simple:
just replace bindService with getApplicationContext().bindService
Now it works perfectly ;-)
I don't think that it is a bug.
In my opinion, that's because when you use the TabActivity, the child activities will be embedded in the parent (TabActivity) as more like a view with activity behavior, hence its context cannot serve as an actual context.
So for the workaround, you need to get and use the parent (using getParent()) or the application context (using getApplicationContext()) which can act as an "actual" context.
But again, this is just my opinion because I cannot provide any link to any documentation related to this one. :)