v4的sample学习--Content/LocalServiceBroadcaster+FileProviderExample

写完这篇,content章节就结束了

首先介绍LocalServiceBroadcaster:

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.supportv4.content;

import com.example.android.supportv4.R;

import android.app.Activity;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.app.ServiceCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

/**
 * Demonstrates the use of a LocalBroadcastManager to easily communicate
 * data from a service to any other interested code.
 */
public class LocalServiceBroadcaster extends Activity {
    static final String ACTION_STARTED = "com.example.android.supportv4.STARTED";
    static final String ACTION_UPDATE = "com.example.android.supportv4.UPDATE";
    static final String ACTION_STOPPED = "com.example.android.supportv4.STOPPED";

    LocalBroadcastManager mLocalBroadcastManager;
    BroadcastReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.local_service_broadcaster);

        // This is where we print the data we get back.
        //这个用来输出我们得到的返回数据
        final TextView callbackData = (TextView)findViewById(R.id.callback);

        // Put in some initial text.放置初始化文本
        callbackData.setText("No broadcast received yet");

        // We use this to send broadcasts within our local process.
        //在我们的本地进程中用这个发送广播
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);

        // We are going to watch for interesting local broadcasts.观察广播
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_STARTED);
        filter.addAction(ACTION_UPDATE);
        filter.addAction(ACTION_STOPPED);
        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(ACTION_STARTED)) {
                    callbackData.setText("STARTED");
                } else if (intent.getAction().equals(ACTION_UPDATE)) {
                    callbackData.setText("Got update: " + intent.getIntExtra("value", 0));
                } else if (intent.getAction().equals(ACTION_STOPPED)) {
                    callbackData.setText("STOPPED");
                }
            }
        };
        mLocalBroadcastManager.registerReceiver(mReceiver, filter);

        // Watch for button clicks.观察按钮点击
        Button button = (Button)findViewById(R.id.start);
        button.setOnClickListener(mStartListener);
        button = (Button)findViewById(R.id.stop);
        button.setOnClickListener(mStopListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocalBroadcastManager.unregisterReceiver(mReceiver);
    }

    private OnClickListener mStartListener = new OnClickListener() {
        public void onClick(View v) {
            startService(new Intent(LocalServiceBroadcaster.this, LocalService.class));
        }
    };

    private OnClickListener mStopListener = new OnClickListener() {
        public void onClick(View v) {
            stopService(new Intent(LocalServiceBroadcaster.this, LocalService.class));
        }
    };

    public static class LocalService extends Service {
        LocalBroadcastManager mLocalBroadcastManager;
        int mCurUpdate;

        static final int MSG_UPDATE = 1;

        Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_UPDATE: {
                        mCurUpdate++;
                        Intent intent = new Intent(ACTION_UPDATE);
                        intent.putExtra("value", mCurUpdate);
                        mLocalBroadcastManager.sendBroadcast(intent);
                        Message nmsg = mHandler.obtainMessage(MSG_UPDATE);
                        mHandler.sendMessageDelayed(nmsg, 1000);
                    } break;
                    default:
                        super.handleMessage(msg);
                }
            }
        };

        @Override
        public void onCreate() {
            super.onCreate();
            mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        }

        public int onStartCommand(Intent intent, int flags, int startId) {
            // Tell any local interested parties about the start.告诉任何本地相关的开始部分
            mLocalBroadcastManager.sendBroadcast(new Intent(ACTION_STARTED));

            // Prepare to do update reports.准备做更新部分
            mHandler.removeMessages(MSG_UPDATE);
            Message msg = mHandler.obtainMessage(MSG_UPDATE);
            mHandler.sendMessageDelayed(msg, 1000);
            /*
            START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。
            随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。
            如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
            */
            return ServiceCompat.START_STICKY;
        }

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

            // Tell any local interested parties about the stop.告诉任何本地相关的停止部分
            mLocalBroadcastManager.sendBroadcast(new Intent(ACTION_STOPPED));

            // Stop doing updates.移除更新消息,停止做更新
            mHandler.removeMessages(MSG_UPDATE);
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
}

这里点击开始按钮开启LocalService,LocalService做的工作是发送broadcast。首先发送ACTION_STARTED,在handle的handleMessage方法中每隔一秒发送更新广播。点结束按钮停止LocalService。

接下来就是LocalBroadcastManager:

 public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        synchronized (mReceivers) {
            ReceiverRecord entry = new ReceiverRecord(filter, receiver);
            ArrayList<IntentFilter> filters = mReceivers.get(receiver);
            if (filters == null) {
                filters = new ArrayList<IntentFilter>(1);
                mReceivers.put(receiver, filters);
            }
            filters.add(filter);
            for (int i=0; i<filter.countActions(); i++) {
                String action = filter.getAction(i);
                ArrayList<ReceiverRecord> entries = mActions.get(action);
                if (entries == null) {
                    entries = new ArrayList<ReceiverRecord>(1);
                    mActions.put(action, entries);
                }
                entries.add(entry);
            }
        }
    }

这里的注册中 new ArrayList<IntentFilter>(1),为的是以后好拓展,以后集合的容量可能会为1以上。

setBroadcase()中:

if (receivers != null) {
                    for (int i=0; i<receivers.size(); i++) {
                        receivers.get(i).broadcasting = false;
                    }
                    mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
                    if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
                        mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
                    }
                    return true;
                }
handle发送了消息,handle的处理:

mHandler = new Handler(context.getMainLooper()) {

            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_EXEC_PENDING_BROADCASTS:
                        executePendingBroadcasts();
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        };
其调用了 executePendingBroadcasts()方法:

private void executePendingBroadcasts() {
        while (true) {
            BroadcastRecord[] brs = null;
            synchronized (mReceivers) {
                final int N = mPendingBroadcasts.size();
                if (N <= 0) {
                    return;
                }
                brs = new BroadcastRecord[N];
                mPendingBroadcasts.toArray(brs);
                mPendingBroadcasts.clear();
            }
            for (int i=0; i<brs.length; i++) {
                BroadcastRecord br = brs[i];
                for (int j=0; j<br.receivers.size(); j++) {
                    br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
                }
            }
        }

关键是这行--br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);也就是说这个LocalBroadcastManager原理是回调方法,所以该方式只能用在一个app单进程中。

接下来是FileProviderExample

直接上代码:

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.supportv4.content;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.content.FileProvider;
import android.view.View;

import com.example.android.supportv4.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Sample that shows how private files can be easily shared.
 * 简单分享文件的例子
 */
public class FileProviderExample extends Activity {
    private static final String AUTHORITY = "com.example.android.supportv4.my_files";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.file_provider_example);
    }

    public void onShareFileClick(View view) {
        // Save a thumbnail to file 保存缩略图文件
        final File thumbsDir = new File(getFilesDir(), "thumbs");
        thumbsDir.mkdirs();
        final File file = new File(thumbsDir, "private.png");
        saveThumbnail(view, file);

        // Now share that private file using FileProvider
        //现在用FileProvider来分享文件
        final Uri uri = FileProvider.getUriForFile(this, AUTHORITY, file);
        final Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("image/png");
        intent.putExtra(Intent.EXTRA_STREAM, uri);
        startActivity(intent);
    }

    /**
     * Save thumbnail of given {@link View} to {@link File}.
     * 以文件的形式保存一个视图的缩略图
     */
    private void saveThumbnail(View view, File file) {
        final Bitmap bitmap = Bitmap.createBitmap(
                view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);

        try {
            final OutputStream os = new FileOutputStream(file);
            try {
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
            } finally {
                os.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

关键点就在 onShareFileClick()方法中:

1.就是文件分享,看到注释就知道了。

2.一个view的缩略图:原理就是调用view的draw方法。详细看saveThumbnail方法,在其中我们也知道怎么获得view相对应的bitmap。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值