草庐IT

android - onBind() 永远不会在服务中被调用

coder 2023-11-22 原文

我正在编写一个带有绑定(bind)服务的基于服务的应用程序,但该服务的 onBind() 方法似乎从未被调用(使用 Toasts 和 Logs 对其进行测试)。

服务:

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.gmail.zack.yovel.FlickAround.MyActivity;
import com.gmail.zack.yovel.FlickAround.R;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 * User: Ziky
 * Date: 09/04/13
 * Time: 19:06
 * To change this template use File | Settings | File Templates.
 */
public class UpdateService extends Service implements LocationListener, UpdatePhotosTask.OnHttpResponseListener {
    private final static String API_KEY = "5255c7b02750c0fa4b15bd8ad4ec1fb7";
    private final static String GET_PHOTOS_FOR_LOCATION_SCHEMA = "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=" + API_KEY + "&lat=%d&lon=%d&format=json&nojsoncallback=1";
    private static final String KEY_PHOTOS = "photos";
    private static final String KEY_PHOTO = "photo";
    private int NOTIFICATION = R.string.update_service_started;
    private NotificationManager mNManager;
    private LocationManager mLManager;
    private String mProvider;
    private Location mLocation;
    private IBinder mBinder = new LocalBinder();
    private UpdatePhotosTask task;

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(this, "UpdateService.onBind()", Toast.LENGTH_LONG).show();
        Log.i("test", "UpdateService.onBind()");
        mLManager.requestLocationUpdates(mProvider, 0, 1000, this);
        return mBinder;
    }

    @Override
    public void onCreate() {
        mNManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        showNotification();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);
        mLManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        mProvider = mLManager.getBestProvider(criteria, false);
        mLocation = mLManager.getLastKnownLocation(mProvider);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        mNManager.cancel(NOTIFICATION);
        Toast.makeText(this, R.string.update_service_stoped, Toast.LENGTH_SHORT).show();
    }

    private void showNotification() {
        CharSequence text = getText(R.string.update_service_active);
        Notification notification = new Notification(R.drawable.refresh, text, System.currentTimeMillis());
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MyActivity.class), 0);
        notification.setLatestEventInfo(this, getText(R.string.update_service_label), text, contentIntent);
        mNManager.notify(NOTIFICATION, notification);
    }

    @Override
    public void onLocationChanged(Location location) {
        beginUpdate(location);
    }

    private void beginUpdate(Location location) {
        Toast.makeText(this, "beginning update", Toast.LENGTH_LONG).show();
        String url = buildUrl(location);
        task = new UpdatePhotosTask(this);
        task.execute(url);
    }

    private String buildUrl(Location location) {
        return String.format(GET_PHOTOS_FOR_LOCATION_SCHEMA, location.getLatitude(), location.getLongitude());
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onHttpResponse(ArrayList<String> responses) {
        if (responses.size() > 0) {
            String response = responses.get(0);
            try {
                JSONObject jsonObject = new JSONObject(response);
                jsonObject = jsonObject.getJSONObject(KEY_PHOTOS);
                JSONArray jsonArray = jsonObject.getJSONArray(KEY_PHOTO);
                ArrayList<String> photos = new ArrayList<String>();
                for (int i = 0, length = jsonArray.length(); i < length; i++) {
                    jsonObject = jsonArray.getJSONObject(i);
                    Log.i("photo info", jsonObject.toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public class LocalBinder extends Binder {
        public UpdateService getService() {
            return UpdateService.this;
        }
    }
}

异步任务:

import android.os.AsyncTask;
import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * Created with IntelliJ IDEA.
 * User: Ziky
 * Date: 09/04/13
 * Time: 07:38
 * To change this template use File | Settings | File Templates.
 */
public class UpdatePhotosTask extends AsyncTask<String, Void, ArrayList<String>> {

    private OnHttpResponseListener listener;

    public UpdatePhotosTask(OnHttpResponseListener listener) {
        this.listener = listener;
    }

    @Override
    protected ArrayList<String> doInBackground(String... urls) {
        ArrayList<String> responses = new ArrayList<String>();
        for (String url : urls) {
            StringBuilder response = new StringBuilder();
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            try {
                HttpResponse execute = client.execute(httpGet);
                StatusLine statusLine = execute.getStatusLine();
                int statusCode = statusLine.getStatusCode();
                if (statusCode == 200) {
                    InputStream content = execute.getEntity().getContent();
                    BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
                    String s = "";
                    while ((s = buffer.readLine()) != null) {
                        response.append(s);
                    }
                    responses.add(response.toString());
                } else {
                    Log.e(this.getClass().toString(), "Failed to download photo list");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responses;
    }

    @Override
    protected void onPostExecute(ArrayList<String> responses) {
        listener.onHttpResponse(responses);
    }

    public interface OnHttpResponseListener {
        public void onHttpResponse(ArrayList<String> responses);
    }
}

Activity :

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.StrictMode;
import android.widget.Toast;
import com.gmail.zack.yovel.FlickAround.background.UpdateService;

public class MyActivity extends Activity {
    private UpdateService mUpdateService;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mUpdateService = ((UpdateService.LocalBinder) service).getService();
            Toast.makeText(MyActivity.this, R.string.update_service_connected, Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mUpdateService = null;
            Toast.makeText(MyActivity.this, R.string.local_service_disconnected, Toast.LENGTH_SHORT).show();
        }
    };
    private boolean mIsBound;

    void doBindService() {
        Toast.makeText(this, "MyActivity.doBindService()", Toast.LENGTH_LONG).show();
        bindService(new Intent(this, UpdateService.class), mConnection, BIND_AUTO_CREATE);
        mIsBound = true;
    }

    void doUnbindService() {
        if (mIsBound) {
            unbindService(mConnection);
            mIsBound = false;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        doUnbindService();
    }

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Activate StrictMode
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll().penaltyLog().penaltyDeath().build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
                .penaltyLog().penaltyDeath().build());
    }

    @Override
    protected void onStart() {
        super.onStart();
        doBindService();
    }
}

为什么它不起作用?

最佳答案

可能导致绑定(bind)失败的最常见原因是没有在 list 中列出服务。这不会引发异常,因此您的应用不会崩溃,但 LogCat 中应该有一条消息(警告,IIRC)指出您的问题。

关于android - onBind() 永远不会在服务中被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15909217/

有关android - onBind() 永远不会在服务中被调用的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  4. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  5. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  6. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  7. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐