android 视频开发2分之2(仿美拍,糗百)
上一篇写了分段录制和合并视频。这一篇则是选择视频,然后截断视频。
1、从sdcard中找到视频资源; 
2、分析视频,拿到你须要的帧数当你的图片。(我的是依据參数来算的多少秒1帧的图片,通常是1秒1帧来显示图片) 
3、给个 可拉动 控件来选择截断区域 。
(我的是基本參数是最少5秒。最大15秒。如需改动。仅仅需改(MIN_TIME,MAX_TIME)这2个參数则以)
先上图: 
 
咱们来看代码。首先是选择视频的:
package com.example.shipin;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
public class VideoNewSelectActivity extends BaseActivity {
    /** 图片展示器 */
    private GridView gridview;
    /** 图片适配器 */
    private ViewNewSelectAdapter adapter;
    /** 数据集 */
    private ArrayList<ViewNewSelectBean> list;
    private ImageView img_back;
    /** 显示图片的宽 */
    private int width;
    @Override
    protected int getContentViewId() {
        return R.layout.activity_video_new_select;
    }
    @SuppressWarnings("deprecation")
    @Override
    protected void findViews() {
        img_back = (ImageView) findViewById(R.id.video_new_img_back);
        gridview = (GridView) findViewById(R.id.video_new_select_gridview);
        width = (getWindowManager().getDefaultDisplay().getWidth() - DisplayUtil.dip2px(VideoNewSelectActivity.this, 60)) / 3;
    }
    @Override
    protected void init() {
        list = new ArrayList<ViewNewSelectBean>();
        adapter = new ViewNewSelectAdapter(list, width, VideoNewSelectActivity.this);
        gridview.setAdapter(adapter);
        getList();
    }
    @Override
    protected void widgetListener() {
        img_back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        gridview.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Bundle bundle = new Bundle();
                bundle.putSerializable("serializable", list.get(position));
                Intent intent = new Intent(VideoNewSelectActivity.this, VideoNewCutActivity.class);
                intent.putExtras(bundle);
                startActivity(intent);
            }
        });
    }
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == 1) {
                adapter.notifyDataSetChanged();
            }
        };
    };
    /**
     * 获取数据
     *
     * @version 1.0
     * @createTime 2015年6月16日,下午6:14:09
     * @updateTime 2015年6月16日,下午6:14:09
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     */
    private void getList() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 若为图片则为MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                Uri originalUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                ContentResolver cr = getContentResolver();
                Cursor cursor = cr.query(originalUri, null, null, null, null);
                if (cursor == null) {
                    return;
                }
                while (cursor.moveToNext()) {
                    ViewNewSelectBean bean = new ViewNewSelectBean();
                    bean.set_id(cursor.getLong(cursor.getColumnIndex("_ID")));
                    bean.setName(cursor.getString(cursor.getColumnIndex("_display_name")));// 视频名字
                    bean.setPath(cursor.getString(cursor.getColumnIndex("_data")));// 路径
                    bean.setWidth(cursor.getInt(cursor.getColumnIndex("width")));// 视频宽
                    bean.setHeight(cursor.getInt(cursor.getColumnIndex("height")));// 视频高
                    bean.setDuration(cursor.getLong(cursor.getColumnIndex("duration")));// 时长
                    list.add(bean);
                }
                Message message = handler.obtainMessage();
                message.what = 1;
                handler.sendMessage(message);
                // /data/data/com.android.providers.media/databases/external.db
                // {5dd10730} 数据库位置
            }
        }).start();
    }
    private class ViewNewSelectAdapter extends BaseAdapter {
        private Context context;
        /** 数据集 */
        private ArrayList<ViewNewSelectBean> list;
        /** 图片宽 */
        private int width;
        public ViewNewSelectAdapter(ArrayList<ViewNewSelectBean> list, int width, Context context) {
            this.list = list;
            this.width = width;
            this.context = context;
        }
        @Override
        public int getCount() {
            return list.size();
        }
        @Override
        public Object getItem(int position) {
            return list.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @SuppressLint("InflateParams")
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder viewHolder;
            final ViewNewSelectBean bean = list.get(position);
            if (convertView == null) {
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(context).inflate(R.layout.item_video_new_select_gridview, null);
                viewHolder.txt = (TextView) convertView.findViewById(R.id.item_video_new_select_txt_time);
                viewHolder.img = (ImageView) convertView.findViewById(R.id.item_video_new_select_img);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            LayoutParams layoutParams = (LayoutParams) viewHolder.img.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = width;
            viewHolder.img.setLayoutParams(layoutParams);
            // 获取图片
            Bitmap bitmap = getVideoThumbnail(bean.getPath(), width, width, MediaStore.Images.Thumbnails.MICRO_KIND);
            if (bitmap != null) {
                // 设置图片
                viewHolder.img.setImageBitmap(bitmap);
            }
            // 设置时长
            viewHolder.txt.setText(String.format("时长:%1$s s", bean.getDuration() / 1000));
            return convertView;
        }
        /**
         * 获取视频的缩略图
         * 先通过ThumbnailUtils来创建一个视频的缩略图,然后再利用ThumbnailUtils来生成指定大小的缩略图。
         * 假设想要的缩略图的宽和高都小于MICRO_KIND,则类型要使用MICRO_KIND作为kind的值,这样会节省内存。
*
         * @param videoPath
         *                视频的路径
         * @param width
         *                指定输出视频缩略图的宽度
         * @param height
         *                指定输出视频缩略图的高度度
         * @param kind
         *                參照MediaStore.Images.
         *                Thumbnails类中的常量MINI_KIND和MICRO_KIND。
         *                当中,MINI_KIND: 512 x 384,MICRO_KIND: 96 x 96
         * @return 指定大小的视频缩略图
         */
        private Bitmap getVideoThumbnail(String videoPath, int width, int height, int kind) {
            Bitmap bitmap = null;
            // 获取视频的缩略图
            bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);
            bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
            return bitmap;
        }
        private class ViewHolder {
            private ImageView img;
            private TextView txt;
        }
    }
}
看到选择之后就到重点部分了,视频截断。首先得从上个activity拿到视频的数据bean,然后通过视频路径。分析视频,通过自己设置的须要多少帧一张的图片来进行取图片。取完图片则是通过android的新控件RecyclerView来进行显示,听说RecyclerView是Listview的升级版(支持横向和竖向)。我还须要他滚动的距离来进行计算切断的位置。RecyclerView貌似拿不到滚动距离,所以咱们得自己计算了(通过拿到当前滑到的position*view的宽度-view距左边的距离就得到滚动距离了)。还有个矩形框来进行拉动选择截断大小哦。好了咱们来看代码吧(代码凝视量还是比較大的,应该都懂,不懂留言给我一一解答):
package com.example.shipin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.LinearLayoutManager;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.VideoView;
import com.example.shipin.MyRecyclerView.OnItemScrollChangeListener;
import com.example.shipin.VideoNewCutAdapter.MyItemClickListener;
public class VideoNewCutActivity extends BaseActivity {
    /**返回*/
    private ImageView img_back;
    /**确认*/
    private TextView txt_enter;
    /** 视频bean */
    private ViewNewSelectBean bean;
    /** 横向listview */
    private MyRecyclerView recyclerView;
    /** 封面图button */
    private ImageView img_bg;
    /** 阴影色块left */
    private ImageView img_left;
    /** 阴影色块right */
    private ImageView img_right;
    /** 显示时间 */
    private TextView txt_time;
    /** 封面容器 */
    private RelativeLayout relative;
    /** 进度条 */
    private RelativeLayout relative1;
    /** 视频播放 */
    private VideoView videoView;
    /** 数据集 */
    private ArrayList<String> list;
    /** 列表适配器 */
    private VideoNewCutAdapter adapter;
    /** 屏幕宽度 */
    private int width;
    /** 暂时保存文件路径 */
    private String savePath;
    /** 最少多少秒 */
    public static final int MIN_TIME = 5000;
    /** 最大多少秒 */
    public static final int MAX_TIME = 15000;
    /** 屏幕中1像素占有多少毫秒 */
    private float picture = 0;
    /** 多少秒一帧 */
    private float second_Z;
    /** 是否中断线性 */
    private boolean isThread = false;
    /** 左边拖动button */
    private Button txt_left;
    /** 右边拖动button */
    private Button txt_right;
    /** 按下时X抽坐标 */
    private float DownX;
    /** 拖动条容器 */
    private LayoutParams layoutParams_progress;
    /** 阴影背景容器 */
    private LayoutParams layoutParams_yin;
    /** 拖动条的宽度 */
    private int width_progress = 0;
    /** 拖动条的间距 */
    private int Margin_progress = 0;
    /** 阴影框的宽度 */
    private int width1_progress = 0;
    /** 不能超过右边多少 */
    private int right_margin = 0;
    /** 全部图片长度 */
    private int img_widthAll = 0;
    /** 最少保留的多少秒长度 */
    private int last_length = 0;
    /** 左边啦了多少 */
    private int left_lenth = 0;
    /** 滚动的长度 */
    private int Scroll_lenth = 0;
    /** 路径 */
    private String Ppath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videoTest/Image/";
    @Override
    protected int getContentViewId() {
        return R.layout.activity_video_new_cut;
    }
    @SuppressWarnings("deprecation")
    @Override
    protected void findViews() {
        img_back = (ImageView) findViewById(R.id.video_new_img_back);
        txt_enter = (TextView) findViewById(R.id.video_new_txt_enter);
        recyclerView = (MyRecyclerView) findViewById(R.id.recyclerview_horizontal);
        videoView = (VideoView) findViewById(R.id.video_new_cut_videoview);
        img_bg = (ImageView) findViewById(R.id.video_new_cut_img_bg);
        img_left = (ImageView) findViewById(R.id.video_new_cut_img_left);
        img_right = (ImageView) findViewById(R.id.video_new_cut_img_right);
        relative = (RelativeLayout) findViewById(R.id.video_new_cut_relative);
        txt_time = (TextView) findViewById(R.id.video_new_cut_txt_time);
        relative1 = (RelativeLayout) findViewById(R.id.video_new_cut_relative1);
        txt_left = (Button) findViewById(R.id.video_new_cut_txt_left);
        txt_right = (Button) findViewById(R.id.video_new_cut_txt_right);
        width = getWindowManager().getDefaultDisplay().getWidth();
        LayoutParams layoutParams = (LayoutParams) relative.getLayoutParams();
        layoutParams.width = width;
        layoutParams.height = width;
        relative.setLayoutParams(layoutParams);
        // 创建一个线性布局管理器
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        // 设置布局管理器
        recyclerView.setLayoutManager(layoutManager);
        list = new ArrayList<String>();
        adapter = new VideoNewCutAdapter(list);
    }
    @Override
    protected void initGetData() {
        super.initGetData();
        if (getIntent().getExtras() != null) {
            bean = (ViewNewSelectBean) getIntent().getExtras().getSerializable("serializable");
        }
    }
    @Override
    protected void init() {
        // 创建目录
        File file = new File(Ppath);
        if (!file.exists()) {
            file.mkdir();
        }
        recyclerView.setAdapter(adapter);
        videoView.setVideoPath(bean.getPath());
        videoView.requestFocus();
        /** 一个屏幕1像素是多少毫秒 13.88888 */
        picture = (float) MAX_TIME / (float) width;
        /** 1.66666 */
        second_Z = (float) MAX_TIME / 1000f / ((float) width / (float) DisplayUtil.dip2px(VideoNewCutActivity.this, 60));
        getBitmapsFromVideo(bean.getPath(), (int) bean.getDuration());
    }
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == 1) {
                adapter.notifyItemInserted(msg.arg1);
                if (msg.arg1 == 0) {
                    sendVideo(DisplayUtil.dip2px(VideoNewCutActivity.this, 60));
                }
            } else if (msg.what == 2) {
                img_widthAll = (int) (msg.arg1 * 1000 / picture);
                last_length = (int) (MIN_TIME / picture);
                if (img_widthAll < width) {
                    right_margin = width - img_widthAll;
                    LayoutParams layoutParams_right = (LayoutParams) img_right.getLayoutParams();
                    layoutParams_right.width = width - img_widthAll;
                    img_right.setLayoutParams(layoutParams_right);
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                    layoutParams_progress.width = img_widthAll;
                    layoutParams_progress.rightMargin = width - img_widthAll;
                    relative1.setLayoutParams(layoutParams_progress);
                    txt_time.setText(msg.arg1 + ".0 s");
                } else {
                    img_widthAll = width;
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                    layoutParams_progress.width = width;
                    relative1.setLayoutParams(layoutParams_progress);
                    txt_time.setText((MAX_TIME / 1000) + ".0 s");
                }
            }
        };
    };
    /**
     * 获取视频帧图片
     *
     * @version 1.0
     * @createTime 2015年6月17日,上午11:49:54
     * @updateTime 2015年6月17日,上午11:49:54
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param dataPath
     * @param lenth
     */
    public void getBitmapsFromVideo(final String dataPath, final int lenth) {
        new Thread(new Runnable() {
            @SuppressLint("NewApi")
            @Override
            public void run() {
                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                retriever.setDataSource(dataPath);
                // 取得视频的长度(单位为秒)
                int seconds = lenth / 1000;
                Message message = handler.obtainMessage();
                message.what = 2;
                message.arg1 = seconds;
                handler.sendMessage(message);
                Bitmap bitmap;
                // 得到每一秒时刻的bitmap比方第一秒,第二秒
                int index = 0;
                for (float f = second_Z; f <= (float) seconds; f += second_Z) {
                    if (isThread) {
                        return;
                    }
                    bitmap = retriever.getFrameAtTime((long) (f * 1000 * 1000), MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                    String path = Ppath + System.currentTimeMillis() + ".jpg";
                    FileOutputStream fos = null;
                    try {
                        fos = new FileOutputStream(path);
                        bitmap.compress(CompressFormat.JPEG, 80, fos);
                        fos.close();
                        list.add(path);
                        Message message1 = handler.obtainMessage();
                        message1.what = 1;
                        message1.arg1 = index;
                        handler.sendMessage(message1);
                        index++;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
    @Override
    protected void widgetListener() {
        /** 列表点击事件 */
        adapter.setOnClickListener(new MyItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                sendVideo((position + 1) * view.getWidth());
            }
        });
        /** 返回 */
        img_back.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        /** 完毕 */
        txt_enter.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.post(runnable3);
            }
        });
        /** 播放 */
        relative.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (videoView.isPlaying()) {
                    img_bg.setVisibility(View.VISIBLE);
                    videoView.pause();
                    handler.removeCallbacks(runnable);
                } else {
                    videoView.setVisibility(View.VISIBLE);
                    img_bg.setVisibility(View.GONE);
                    videoView.start();
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                    // 会误差 200-800毫秒
                    handler.postDelayed(runnable, (long) (layoutParams_progress.width * picture) + 500);
                }
            }
        });
        /** 左边拖动button */
        txt_left.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    DownX = event.getRawX();
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                    layoutParams_yin = (LayoutParams) img_left.getLayoutParams();
                    width_progress = layoutParams_progress.width;
                    Margin_progress = layoutParams_progress.leftMargin;
                    width1_progress = layoutParams_yin.width;
                    break;
                case MotionEvent.ACTION_MOVE:
                    LeftMoveLayout(event.getRawX() - DownX, event.getRawX());
                    break;
                case MotionEvent.ACTION_UP:
                    sendVideo();
                    layoutParams_progress = null;
                    layoutParams_yin = null;
                    break;
                default:
                    break;
                }
                return false;
            }
        });
        /** 右边拖动button */
        txt_right.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    DownX = event.getRawX();
                    layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                    layoutParams_yin = (LayoutParams) img_right.getLayoutParams();
                    width_progress = layoutParams_progress.width;
                    Margin_progress = layoutParams_progress.rightMargin;
                    width1_progress = layoutParams_yin.width;
                    break;
                case MotionEvent.ACTION_MOVE:
                    RightMoveLayout(DownX - event.getRawX());
                    break;
                case MotionEvent.ACTION_UP:
                    layoutParams_progress = null;
                    layoutParams_yin = null;
                    break;
                default:
                    break;
                }
                return false;
            }
        });
        /** 视频播放完回调 */
        videoView.setOnCompletionListener(new OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                img_bg.setVisibility(View.VISIBLE);
                handler.removeCallbacks(runnable);
            }
        });
        /** 滚动监听 */
        recyclerView.setOnItemScrollChangeListener(new OnItemScrollChangeListener() {
            @Override
            public void onChange(View view, int position) {
                Scroll_lenth = position * view.getWidth() - view.getLeft();
                if (Scroll_lenth <= 0) {
                    Scroll_lenth = 0;
                }
//               sendVideo();//打开凝视就是边滑动变更新视图
            }
            @Override
            public void onChangeState(int state) {
                if (state == 0) {// 精巧情况时候才调用
                    sendVideo();
                }
            }
        });
    }
    private Runnable runnable3 = new Runnable() {
        @Override
        public void run() {
            try {
                layoutParams_progress = (LayoutParams) relative1.getLayoutParams();
                savePath = Ppath + System.currentTimeMillis() + ".mp4";
                FUckTest.startTrim(new File(bean.getPath()), new File(savePath), (long) ((Scroll_lenth + left_lenth) * picture), (long) ((Scroll_lenth
                        + left_lenth + layoutParams_progress.width) * picture));
                Intent it = new Intent(VideoNewCutActivity.this,VideoActivity.class);
                it.putExtra("path", savePath);
                startActivity(it);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    /**
     * 向右边啦
     *
     * @version 1.0
     * @createTime 2015年6月18日,上午9:44:32
     * @updateTime 2015年6月18日,上午9:44:32
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param MoveX
     */
    private void LeftMoveLayout(float MoveX, float X) {
        if (layoutParams_progress != null && layoutParams_yin != null) {
            if (Margin_progress + (int) MoveX > 0 && width_progress - (int) MoveX > last_length) {
                layoutParams_progress.width = width_progress - (int) MoveX;
                layoutParams_progress.leftMargin = Margin_progress + (int) MoveX;
                layoutParams_yin.width = width1_progress + (int) MoveX;
                relative1.setLayoutParams(layoutParams_progress);
                img_left.setLayoutParams(layoutParams_yin);
                txt_time.setText((float) (Math.round((layoutParams_progress.width * picture / 1000) * 10)) / 10 + " s");
                left_lenth = layoutParams_yin.width;
            }
        }
    }
    /**
     * 向左边拉
     *
     * @version 1.0
     * @createTime 2015年6月18日,上午9:45:16
     * @updateTime 2015年6月18日,上午9:45:16
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param MoveX
     */
    private void RightMoveLayout(float MoveX) {
        if (layoutParams_progress != null && layoutParams_yin != null) {
            if (Margin_progress + (int) MoveX > right_margin && width_progress - (int) MoveX > last_length) {
                layoutParams_progress.width = width_progress - (int) MoveX;
                layoutParams_progress.rightMargin = Margin_progress + (int) MoveX;
                layoutParams_yin.width = width1_progress + (int) MoveX;
                txt_time.setText((float) (Math.round((layoutParams_progress.width * picture / 1000) * 10)) / 10 + " s");
                relative1.setLayoutParams(layoutParams_progress);
                img_right.setLayoutParams(layoutParams_yin);
            }
        }
    }
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (!img_bg.isShown()) {
                img_bg.setVisibility(View.VISIBLE);
            }
            if (videoView.isPlaying()) {
                videoView.pause();
            }
        }
    };
    /**
     * 移动起始播放位置
     *
     * @version 1.0
     * @createTime 2015年6月18日,下午2:34:31
     * @updateTime 2015年6月18日,下午2:34:31
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param proSlide
     */
    private void sendVideo() {
        if (!videoView.isShown()) {
            videoView.setVisibility(View.VISIBLE);
        }
        if (videoView.isPlaying()) {
            videoView.pause();
        }
        if (!img_bg.isShown()) {
            img_bg.setVisibility(View.VISIBLE);
        }
        handler.removeCallbacks(runnable);
        videoView.seekTo((int) ((Scroll_lenth + left_lenth) * picture));
    }
    /**
     * 移动起始播放位置
     *
     * @version 1.0
     * @createTime 2015年6月18日,下午6:09:50
     * @updateTime 2015年6月18日,下午6:09:50
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param lenth
     *                长度
     */
    private void sendVideo(int lenth) {
        if (!videoView.isShown()) {
            videoView.setVisibility(View.VISIBLE);
        }
        if (videoView.isPlaying()) {
            videoView.pause();
        }
        if (!img_bg.isShown()) {
            img_bg.setVisibility(View.VISIBLE);
        }
        handler.removeCallbacks(runnable);
        videoView.seekTo((int) (lenth * picture));
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        isThread = true;
        deleteFile();
    }
    /**
     * 退出时删除暂时文件
     *
     * @version 1.0
     * @createTime 2015年6月17日,下午1:58:52
     * @updateTime 2015年6月17日,下午1:58:52
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     */
    private void deleteFile() {
        for (int i = 0; i < list.size(); i++) {
            File file = new File(list.get(i));
            if (file.exists()) {
                file.delete();
            }
        }
    }
}
如今是自己定义RecyclerView:
package com.utoow.diver.view;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.util.AttributeSet;
import android.view.View;
public class MyRecyclerView extends RecyclerView implements OnScrollListener {
    /**记录当前第一个View*/
    private View mCurrentView;
    private OnItemScrollChangeListener mItemScrollChangeListener;
    public void setOnItemScrollChangeListener(OnItemScrollChangeListener mItemScrollChangeListener) {
        this.mItemScrollChangeListener = mItemScrollChangeListener;
    }
    public interface OnItemScrollChangeListener {
        void onChange(View view, int position);
        void onChangeState(int state);
    }
    public MyRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnScrollListener(this);
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }
    @Override
    public void onScrollStateChanged(int arg0) {
        if (mItemScrollChangeListener != null) {
            mItemScrollChangeListener.onChangeState(arg0);
        }
    }
    /**
     * 滚动时,推断当前第一个View是否发生变化。发生才回调
     *
     * @version 1.0
     * @createTime 2015年6月20日,下午4:14:30
     * @updateTime 2015年6月20日,下午4:14:30
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param arg0
     * @param arg1
     */
    @Override
    public void onScrolled(int arg0, int arg1) {
        mCurrentView = getChildAt(0);
        if (mItemScrollChangeListener != null && mCurrentView != null) {
            mItemScrollChangeListener.onChange(mCurrentView, getChildPosition(mCurrentView));
        }
    }
}
最后再把视频截断和视频合并的工具类贴出来:
package com.example.shipin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import com.coremedia.iso.boxes.Container;
import com.coremedia.iso.boxes.TimeToSampleBox;
import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.googlecode.mp4parser.authoring.tracks.AppendTrack;
import com.googlecode.mp4parser.authoring.tracks.CroppedTrack;
public class FUckTest {
    public static void startTrim(File src, File dst, long start, long end) throws IOException {
        Movie movie = MovieCreator.build(src.getAbsolutePath());
        // 删除全部跟踪我们将创建新的跟踪从旧
        List<Track> tracks = movie.getTracks();
        movie.setTracks(new LinkedList<Track>());
        double startTime = start / 1000;
        double endTime = end / 1000;
        boolean timeCorrected = false;
        // 我们试图找到一个样品同步跟踪。由于我们仅仅能開始解码在这样一个样品我们应该确保新的片段的開始就是这种一个框架
        for (Track track : tracks) {
            if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
                if (timeCorrected) {
                    // 这个异常可能是假阳性,以防我们有多个与同步跟踪样品在同样的位置。
比方一部电影包括多个品质同样的视频(微软平滑流媒体文件)
                    throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
                }
                startTime = correctTimeToSyncSample(track, startTime, false);// true
                endTime = correctTimeToSyncSample(track, endTime, true);// false
                timeCorrected = true;
            }
        }
        for (Track track : tracks) {
            long currentSample = 0;
            double currentTime = 0;
            long startSample = -1;
            long endSample = -1;
            for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
                TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
                for (int j = 0; j < entry.getCount(); j++) {
                    // entry.getDelta()的数量当前样本覆盖。
if (currentTime <= startTime) {
                        // 眼下的样品仍然在新的開始时间之前
                        startSample = currentSample;
                    }
                    if (currentTime <= endTime) {
                        // 当前样本后,新的開始时间和仍在新endtime前
                        endSample = currentSample;
                    } else {
                        // 眼下样品结束后出现的视频
                        break;
                    }
                    currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
                    currentSample++;
                }
            }
            movie.addTrack(new CroppedTrack(track, startSample, endSample));
            // break;//取消凝视。仅仅截视频不截音频
        }
        Container container = new DefaultMp4Builder().build(movie);
        if (!dst.exists()) {
            dst.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(dst);
        FileChannel fc = fos.getChannel();
        container.writeContainer(fc);
        fc.close();
        fos.close();
    }
    /**
     * 视频拼接,
     *
     * @version 1.0
     * @createTime 2015年6月10日,下午5:12:15
     * @updateTime 2015年6月10日,下午5:12:15
     * @createAuthor WangYuWen
     * @updateAuthor WangYuWen
     * @updateInfo (此处输入改动内容,若无改动可不写.)
     *
     * @param videos
     *                视频文件数据。
《路径》
     * @param desName
     *                合并之后的文件名称
     * @param pro
     * @throws IOException
     */
    public static void appendVideo(String[] videos, String desName) throws IOException {
        Movie[] inMovies = new Movie[videos.length];
        int index = 0;
        for (String video : videos) {
            inMovies[index] = MovieCreator.build(video);
            index++;
        }
        List<Track> videoTracks = new LinkedList<Track>();
        List<Track> audioTracks = new LinkedList<Track>();
        for (Movie m : inMovies) {
            for (Track t : m.getTracks()) {
                if (t.getHandler().equals("soun")) {
                    audioTracks.add(t);
                }
                if (t.getHandler().equals("vide")) {
                    videoTracks.add(t);
                }
            }
        }
        Movie result = new Movie();
        if (audioTracks.size() > 0) {
            result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
        }
        if (videoTracks.size() > 0) {
            result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
        }
        Container out = new DefaultMp4Builder().build(result);
        FileChannel fc = new RandomAccessFile(String.format(desName), "rw").getChannel();
        out.writeContainer(fc);
        fc.close();
    }
    protected static long getDuration(Track track) {
        long duration = 0;
        for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
            duration += entry.getCount() * entry.getDelta();
        }
        return duration;
    }
    private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
        double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
        long currentSample = 0;
        double currentTime = 0;
        for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
            TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
            for (int j = 0; j < entry.getCount(); j++) {
                if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
                    // 样品总是从1開始,但我们从零因此+ 1開始
                    timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
                }
                currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
                currentSample++;
            }
        }
        double previous = 0;
        for (double timeOfSyncSample : timeOfSyncSamples) {
            if (timeOfSyncSample > cutHere) {
                if (next) {
                    return timeOfSyncSample;
                } else {
                    return previous;
                }
            }
            previous = timeOfSyncSample;
        }
        return timeOfSyncSamples[timeOfSyncSamples.length - 1];
    }
}
好了,代码比較长。假设有不懂能够留言。(还有就是有的视频文件比較大就算切断了之后也有30多M,假设说这用到项目中肯定须要上传到server的肯定是不行的,须要的你们能够自己去研究下压缩视频,一般须要用到ffmgep这个c库来进行压缩,顺便说下ffmpeg这个c库真的非常不错非常成熟值得研究)。
最后就是: 
希望大家多多关注我的博客,多多支持我。  
如有好意见或更好的方式欢迎留言谈论。
尊重原创转载请注明:(http://blog.csdn.net/u013895206) !
以下是地址传送门:  
http://download.csdn.net/detail/u013895206/8850751
android 视频开发2分之2(仿美拍,糗百)的更多相关文章
- android 视频开发2分之1(仿美拍,糗百)
		近期比較忙,非常久没更新博客,今天我们仿一个美拍或者糗事百科的录像功能. 首先确认步奏: 1.打开摄像头: 2.開始录制: 3.支持分段录制,并支持分段删除: 4.把分段录制的视频进行合并: 不说废话 ... 
- Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)
		本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ... 
- Android IOS WebRTC 音视频开发总结(八十三)-- 使用WebRTC广播网络摄像头视频(上)
		本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ... 
- 本人讲课时录制的Android应用开发技术教学视频
		网盘地址:http://yun.baidu.com/pcloud/album/info?query_uk=1963923831&album_id=3523786484935252365 本人讲 ... 
- 移动开发 android 入门开发 阶段视频
		一直想把 android 的开发学习录制成视频,这里录制了一部分供大家学习. http://www.chuanke.com/s5402069.html 到这里,文档,源码,视频基本就全了,祝愿大家能够 ... 
- Android IOS WebRTC 音视频开发总结(四六)-- 从另一个角度看国内首届WebRTC大会
		文章主要从开发者角度谈国内首届WebRTC大会,支持原创,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,更多详见www.rtc.help. -------------------- ... 
- Android IOS WebRTC 音视频开发总结(六)-- iOS开发之含泪经验
		前段时间在搞webrtc iOS开发,所以将标题改为了Android IOS WebRTC 音视频开发总结, 下面都是开发过程中的经验总结,转载请说明出处(博客园RTC.Blacker): 1. IO ... 
- Android 音视频开发学习思路
		Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ... 
- Android 音视频开发(一) : 通过三种方式绘制图片
		版权声明:转载请说明出处:http://www.cnblogs.com/renhui/p/7456956.html 在 Android 音视频开发学习思路 里面,我们写到了,想要逐步入门音视频开发,就 ... 
随机推荐
- (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列
			Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ... 
- 搭建rsync实时同步
			1.本实验基于centos6.5服务器做的 cat cat /etc/redhat-release 2.在配置环境之前需要先将服务器自带的rsync卸除 yum -y remove rsync* 3. ... 
- jQuery第四课  点击 _选项卡效果一
			//鼠标移到上面是显示手型cursor:pointer jquery 的函数: siblings //兄弟节点,同胞元素 :eq()选择器选取带有指定 index 值的元素.index 值从 0 开始 ... 
- linux 下的小知识
			Linux中有7种启动级别 运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆运行级别2:多用户状态(没有NFS ... 
- Laravel修炼:服务容器绑定与解析
			前言 老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,因为真的没接触过,对我这种渣渣来说,laravel的入门门槛确实有点高了,但还是得硬着头皮看下去(虽然到现在我还有很多 ... 
- TextView超链接
			这里面涉及两个知识点--超链接和跳转.以下进行逐一解说: 1.实现超链接: 1.1形成超链接文本 public static SpannableString getUserlink(String us ... 
- Ryu基本操作的REST API调用演示样例
			import urllib2 import json def get_all_switches(): url = "http://127.0.0.1:8080/v1.0/topology/s ... 
- USACO Ski Course Design解析和C语言实现
			题目大意: John农场有N(1=<N<=1000)小丘陵(山),它们高度的范围从0 到 100 但仅仅有当最大的高度差不大于17时.才干够避税.John对它们进行改造,从高的丘陵上取土放 ... 
- List of content management systems
			https://en.wikipedia.org/wiki/List_of_content_management_systems Microsoft ASP.NET Name Platform Sup ... 
- 84.Node.js -Mongoose 方法
			转自:https://www.cnblogs.com/chris-oil/p/9136534.html Mongoose 参考手册 标签(空格分隔): MongoDB Mongoose 是什么? 一般 ... 
