Android Beam文件分享失败问题单处理

     昨天收到测试同事提的一个问题单,一个大文件,使用Android Beam分享失败。自己拿到之后,先进行了下测试,真是,找了个Nexus原生机对比一下,怪了,原生机是成功的。那就说明修改原生的问题哪里出错了,好了,开始干活吧。

     再进行验证,先把现象搞清楚,首先找测试同事要到他测试的原视频,大小是843M,用这个反复测了多次,一直失败。好了,自己随便录制一段,再进行Beam分享,咦,好奇怪啊,我录制的视频分享成功!!不对,还不能确定,再试,拿测试同事的视频试一下,还是失败,难道是文件的问题?对比文件看了一下,哦,测试同事提供的文件命名中有中文字符。好,那我把自己录的名字改成中文的,再测试一下,也失败,OK了,看来不是文件差别引起的,可能跟命名当中带有的中文字符有关了。这就是一点眉目,再继续试,现在的分享是从文件管理器中进去的,录制的视频也可以直接从图库中找到,那么相同的文件,从图库中进去执行Beam分享,我靠,神奇了,从图库中进去执行分享,同一个文件,而且命名也有中文字符,是成功的!哇,有收获,不错,进一步明确了差异。现在的初步结论应该是容易确定了,如果从图库中进入,那么无论要分享的文件命名当中是否包含中文,都可以成功,而如果从文件管理器进入,执行分享,那么此时的文件名如果有中文,则必现失败。

     有了补步的现象,接下来,我们就要对这个现象进一步分析了,差别是在哪里呢?首先来看一下NFC beam分享功能,beam的属于系统提供的功能,所以它的代码位于packages包下面,因为beam功能是对应有分享和接收两侧的,所以这里会对应有send和receive,当我们选中一个文件,点击beam分享时,就会执行BeamManager类的startBeamSend方法,大家从BeamManager类的方法当中也可以看到,既有发送,又有接收,整个类的代码如下:

/**
 * Manager for starting and stopping Beam transfers. Prevents more than one transfer from
 * happening at a time.
 */
public class BeamManager implements Handler.Callback {
    private static final String TAG = "BeamManager";
    private static final boolean DBG = false;

    private static final String ACTION_WHITELIST_DEVICE =
            "android.btopp.intent.action.WHITELIST_DEVICE";
    public static final int MSG_BEAM_COMPLETE = 0;

    private final Object mLock;

    private boolean mBeamInProgress;
    private final Handler mCallback;

    private NfcService mNfcService;

    private static final class Singleton {
        public static final BeamManager INSTANCE = new BeamManager();
    }

    private BeamManager() {
        mLock = new Object();
        mBeamInProgress = false;
        mCallback = new Handler(Looper.getMainLooper(), this);
        mNfcService = NfcService.getInstance();
    }

    public static BeamManager getInstance() {
        return Singleton.INSTANCE;
    }

    public boolean isBeamInProgress() {
        synchronized (mLock) {
            return mBeamInProgress;
        }
    }

    public boolean startBeamReceive(Context context,
                                 HandoverDataParser.BluetoothHandoverData handoverData) {
        synchronized (mLock) {
            if (mBeamInProgress) {
                return false;
            } else {
                mBeamInProgress = true;
            }
        }

        BeamTransferRecord transferRecord =
                BeamTransferRecord.forBluetoothDevice(
                        handoverData.device, handoverData.carrierActivating, null);

        Intent receiveIntent = new Intent(context.getApplicationContext(),
                BeamReceiveService.class);
        receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
        receiveIntent.putExtra(BeamReceiveService.EXTRA_BEAM_COMPLETE_CALLBACK,
                new Messenger(mCallback));
        whitelistOppDevice(context, handoverData.device);
        context.startServiceAsUser(receiveIntent, UserHandle.CURRENT);
        return true;
    }

    public boolean startBeamSend(Context context,
                               HandoverDataParser.BluetoothHandoverData outgoingHandoverData,
                               Uri[] uris, UserHandle userHandle) {
        synchronized (mLock) {
            if (mBeamInProgress) {
                return false;
            } else {
                mBeamInProgress = true;
            }
        }

        BeamTransferRecord transferRecord = BeamTransferRecord.forBluetoothDevice(
                outgoingHandoverData.device, outgoingHandoverData.carrierActivating,
                uris);
        Intent sendIntent = new Intent(context.getApplicationContext(),
                BeamSendService.class);
        sendIntent.putExtra(BeamSendService.EXTRA_BEAM_TRANSFER_RECORD, transferRecord);
        sendIntent.putExtra(BeamSendService.EXTRA_BEAM_COMPLETE_CALLBACK,
                new Messenger(mCallback));
        context.startServiceAsUser(sendIntent, userHandle);
        return true;
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == MSG_BEAM_COMPLETE) {
            synchronized (mLock) {
                mBeamInProgress = false;
            }

            boolean success = msg.arg1 == 1;
            if (success) {
                mNfcService.playSound(NfcService.SOUND_END);
            }
            return true;
        }
        return false;
    }

    void whitelistOppDevice(Context context, BluetoothDevice device) {
        if (DBG) Log.d(TAG, "Whitelisting " + device + " for BT OPP");
        Intent intent = new Intent(ACTION_WHITELIST_DEVICE);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        context.sendBroadcastAsUser(intent, UserHandle.CURRENT);
    }

}
     可以从startBeamSend方法当中看到,后边的发送事件是通过BeamSendService来完成的,这里还请大家注意,方法参数Uri[] uris正是保存了我们要分享的目标文件的uri,数据都是在这里的。好了,通过调用context.startServiceAsUser(sendIntent, userHandle)就把BeamSendService启动起来了。那我们再来看一下BeamSendService类的代码。

public class BeamSendService extends Service implements BeamTransferManager.Callback {
    private static String TAG = "BeamSendService";
    private static boolean DBG = true;

    public static String EXTRA_BEAM_TRANSFER_RECORD
            = "com.android.nfc.beam.EXTRA_BEAM_TRANSFER_RECORD";
    public static final String EXTRA_BEAM_COMPLETE_CALLBACK
            = "com.android.nfc.beam.TRANSFER_COMPLETE_CALLBACK";

    private BeamTransferManager mTransferManager;
    private BeamStatusReceiver mBeamStatusReceiver;
    private boolean mBluetoothEnabledByNfc;
    private Messenger mCompleteCallback;
    private int mStartId;

    private final BluetoothAdapter mBluetoothAdapter;
    private final BroadcastReceiver mBluetoothStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                handleBluetoothStateChanged(intent);
            }
        }
    };

    public BeamSendService() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    }

    @Override
    public void onCreate() {
       super.onCreate();

        // register BT state receiver
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(mBluetoothStateReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mBeamStatusReceiver != null) {
            unregisterReceiver(mBeamStatusReceiver);
        }
        unregisterReceiver(mBluetoothStateReceiver);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mStartId = startId;

        BeamTransferRecord transferRecord;
        if (intent == null ||
               (transferRecord = intent.getParcelableExtra(EXTRA_BEAM_TRANSFER_RECORD)) == null) {
            if (DBG) Log.e(TAG, "No transfer record provided. Stopping.");
            stopSelf(startId);
            return START_NOT_STICKY;
        }

        mCompleteCallback = intent.getParcelableExtra(EXTRA_BEAM_COMPLETE_CALLBACK);

        if (doTransfer(transferRecord)) {
            if (DBG) Log.i(TAG, "Starting outgoing Beam transfer");
            return START_STICKY;
        } else {
            invokeCompleteCallback(false);
            stopSelf(startId);
            return START_NOT_STICKY;
        }
    }

    boolean doTransfer(BeamTransferRecord transferRecord) {
        if (createBeamTransferManager(transferRecord)) {
            // register Beam status receiver
            mBeamStatusReceiver = new BeamStatusReceiver(this, mTransferManager);
            registerReceiver(mBeamStatusReceiver, mBeamStatusReceiver.getIntentFilter(),
                    BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler());

            if (transferRecord.dataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
                if (mBluetoothAdapter.isEnabled()) {
                    // Start the transfer
                    mTransferManager.start();
                } else {
                    if (!mBluetoothAdapter.enableNoAutoConnect()) {
                        Log.e(TAG, "Error enabling Bluetooth.");
                        mTransferManager = null;
                        return false;
                    }
                    mBluetoothEnabledByNfc = true;
                    if (DBG) Log.d(TAG, "Queueing out transfer "
                            + Integer.toString(transferRecord.id));
                }
            }
            return true;
        }

        return false;
    }

    boolean createBeamTransferManager(BeamTransferRecord transferRecord) {
        if (mTransferManager != null) {
            return false;
        }

        if (transferRecord.dataLinkType != BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
            // only support BT
            return false;
        }

        mTransferManager = new BeamTransferManager(this, this, transferRecord, false);
        mTransferManager.updateNotification();
        return true;
    }

    private void handleBluetoothStateChanged(Intent intent) {
        int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                BluetoothAdapter.ERROR);
        if (state == BluetoothAdapter.STATE_ON) {
            if (mTransferManager != null &&
                    mTransferManager.mDataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
                mTransferManager.start();
            }
       } else if (state == BluetoothAdapter.STATE_OFF) {
            mBluetoothEnabledByNfc = false;
        }
    }

    private void invokeCompleteCallback(boolean success) {
        if (mCompleteCallback != null) {
            try {
                Message msg = Message.obtain(null, BeamManager.MSG_BEAM_COMPLETE);
                msg.arg1 = success ? 1 : 0;
                mCompleteCallback.send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "failed to invoke Beam complete callback", e);
            }
       
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红-旺永福

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值