模仿抖音app源碼 但可以離線看視頻,批量上傳視頻,調進度,右邊滑動調節聲音,左邊翻頁,自動同步更新遠程上傳視頻,自動升級,記錄位置


仿抖音安卓apk演示:https://pan.baidu.com/s/1WoCU5cUFYC3T4zoV3mh3uQ


視頻可以批量上傳:http://7.wjsou.com

開發環境:ADT (Eclipse) 或Android Studio 導入可以二次開發。

功能:模仿抖音app,可以離線看視頻,批量上傳視頻,調進度,右邊滑動調節聲音,左邊翻頁,自動同步更新遠程上傳視頻,記錄位置



服務器內容:


其中的video_version.txt格式內容:

[{"NO":"1","Name":"model.mp4"},{"NO":"2","Name":"adv.mp4"}]

NO沒有使用。可以不寫。只用把視頻名稱Name加入就行。


使用說明:

把serverupdatefile文件夾下的視頻文件及視頻配置文件video_version.txt放到服務器上。

如果要放在你服務器上,請改寫項目下面路徑:


源碼:

package com.example.video;

import java.io.File;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.format.Time;
import android.util.Log;
import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

public class PlayActivity extends Activity {
	public boolean nextFlag=false;
	public float f=0;
	public static final String CURRENT="current"; //配置項:當前播放位置

	 private GestureDetector mGestureDetector;
    /** 最大聲音 */
    private int mMaxVolume;
    /** 當前聲音 */
    private int mVolume = -1;
    private AudioManager mAudioManager;
    
	private int current=0;
	private UpdateManager updateMan;
	//private ProgressDialog updateProgressDialog;
	
	private VideoView videoView;
	private  LinearLayout ll_update_content;
	private TextView tv_update_content;
	private ProgressBar progressbar_update_content;
	private TextView tv_volume;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_play);
		videoView = (VideoView) findViewById(R.id.videoView1);
		MediaController controller = new MediaController(this);
		videoView.setMediaController(controller);
		
		ll_update_content = (LinearLayout) findViewById(R.id.update_content);
		tv_update_content = (TextView) findViewById(R.id.textView_update_content);
		progressbar_update_content = (ProgressBar) findViewById(R.id.progressBar1);
		ll_update_content.setVisibility(View.GONE);
		
		tv_volume= (TextView) this.findViewById(R.id.textViewVolume);
		tv_volume.setVisibility(View.GONE);
		 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
         mMaxVolume = mAudioManager
                 .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		mGestureDetector = new GestureDetector(this, new MyGestureListener());
		//沒有判斷網路是否連接的提示
        
        
        //檢查是否有更新
        //如果有更新提示下載
        updateMan = new UpdateManager(PlayActivity.this, appUpdateCb);
        
		//讀取當前播放位置
		SharedPreferences sharedata1 = getSharedPreferences(UpdateManager.CONFIG, 0);	
		current = sharedata1.getInt(CURRENT, 0);
		if(current>=updateMan.localSaveName.size())
			current=0;
		
        play();
		updateMan.checkUpdate();

		//limited();
		}
	public void saveCurrent() // 保存當前播放位置
	{
		SharedPreferences.Editor sharedata = getSharedPreferences(UpdateManager.CONFIG, 0).edit();
		sharedata.putInt(CURRENT, current);
		sharedata.commit();
	}
	public void play()
	{
        try{
	        if(updateMan.localSaveName.size()>0)
	        {
	        	playVideo();
	        }
	        else
	        	Toast.makeText(this, "沒有要播放的視頻,請在服務器上更新2", Toast.LENGTH_SHORT).show();
        }catch(Exception e){
        	Toast.makeText(this, "沒有要播放的視頻,請在服務器上更新1", Toast.LENGTH_SHORT).show();
        }
	}
	public void playVideo()
	{


		//下面android:resource://是固定的,org.dengzh是我的包名,不是.java文件package名稱,R.raw.movie_1是id名稱
		//videoView.setVideoURI(Uri.parse("android.resource://com.example.video/"+R.raw.video));
		//videoView.setVideoURI(Uri.parse(updateMan.savefolder+updateMan.localSaveName.get(i)));
		videoView.setVideoPath(updateMan.savefolder+updateMan.localSaveName.get(current));  
		
		//監聽視頻播放完的代碼
		videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
		        
		    @Override
		    public void onCompletion(MediaPlayer mPlayer) {
		    // TODO Auto-generated method stub
		    	current++;
		    	if(current>=updateMan.localSaveName.size())
		    		current=0;
				videoView.setVideoPath(updateMan.savefolder+updateMan.localSaveName.get(current));  		
				videoView.start();  
				saveCurrent(); // 保存當前播放位置
				
	            // 提示
	            tv_volume.setText(""+current+" "+updateMan.localSaveName.get(current));
                // 顯示
                tv_volume.setVisibility(View.VISIBLE);
	            // 隱藏				
	            mDismissHandler.removeMessages(0);
	            mDismissHandler.sendEmptyMessageDelayed(0, 500);
		    }
		});
		 /* 開始播放視頻 */  
		videoView.start();  
          
        /*  請求獲取焦點 */  
		//videoView.requestFocus();  
	}
		void limited() {
			Time t = new Time(); // or Time t=new Time("GMT+8"); 加上Time Zone資料。
			t.setToNow(); // 取得系統時間。

			String time = t.year + "年 " + (t.month + 1) + "月 " + t.monthDay + "日 "
					+ t.hour + "h " + t.minute + "m " + t.second;
			Log.e("msg", time);
			//if (t.year == 2014 && t.month + 1 == 9 && t.monthDay == 23) 測試
				if(t.year!=2017 )//這個月	|| (t.month+1)!=11
			// if(t.year!=2014 || (t.month+1)!=9||t.monthDay!=23) //今天
			{
				 Toast.makeText(this,"調用版時間到自動退出,請聯繫軟件作者QQ:40078329" ,
				 Toast.LENGTH_LONG).show();
				 
					new Handler().postDelayed(new Runnable(){   //延遲執行
						@Override
						public void run(){
							android.os.Process
							.killProcess(android.os.Process
									.myPid()); // 終止線程
						}
					}, 3000);
			}
		}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.play, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_delete) {
			for(int i=0;i<UpdateManager.localSaveName.size();i++)
			{
                File filefolder = new File(UpdateManager.savefolder);  
              //判斷文件夾是否存在,如果不存在就創建,否則不創建  
                if (!filefolder.exists()) {  		         
                	filefolder.mkdirs();  
                }  
                File File = new File(UpdateManager.savefolder,UpdateManager.localSaveName.get(i));
                if(File.exists())
                {            
                	File.delete();
                }
			}
			SharedPreferences.Editor sharedata = getSharedPreferences(UpdateManager.CONFIG, 0).edit();
			sharedata.clear();
			sharedata.commit();
			UpdateManager.localSaveName.clear();
			Toast.makeText(this, "已經刪除所有本地文件", Toast.LENGTH_SHORT).show();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
	
	 // 自動更新回調函數
		UpdateManager.UpdateCallback appUpdateCb = new UpdateManager.UpdateCallback() 
		{

			public void downloadProgressChanged(int progress) {
				progressbar_update_content.setProgress(progress);	
			}

			public void downloadCompleted(Boolean sucess, CharSequence errorMsg) {
				ll_update_content.setVisibility(View.GONE);	
				if (sucess) {
					updateMan.update();
					if(!videoView.isPlaying())
						play(); //播放操作
					if(updateMan.needSaveName.size()>0)
						updateMan.checkUpdate();  //繼續更新下一個
					
				} else {
					tv_update_content.setText("下載出錯,正在重試:");				
					updateMan.downloadPackage();
				}
			}

			public void downloadCanceled() 
			{
				// TODO Auto-generated method stub

			}

			public void checkUpdateCompleted(Boolean hasUpdate,
					CharSequence updateInfo) {
				if (hasUpdate) {					
					ll_update_content.setVisibility(View.VISIBLE);
					tv_update_content.setText("正在更新:"+updateInfo);
					progressbar_update_content.setMax(100);
					progressbar_update_content.setProgress(0);					
					updateMan.downloadPackage();					
				}

			}
		};
		
		 @Override
	        public boolean onTouchEvent(MotionEvent event) {
	           
				if (mGestureDetector.onTouchEvent(event))
	                return true;
	    
	            // 處理手勢結束
	            switch (event.getAction() & MotionEvent.ACTION_MASK) {
	            case MotionEvent.ACTION_UP:
	                endGesture();
	                break;
	            }
	    
	            return super.onTouchEvent(event);
	        }
		 /** 手勢結束 */
	        private void endGesture() {
	        	if(nextFlag)
	        	{
	        		onNextSlide(f);
	        		nextFlag=false;
	        	}
	        	
	            mVolume = -1;
	          	    
	            // 隱藏
	            mDismissHandler.removeMessages(0);
	            mDismissHandler.sendEmptyMessageDelayed(0, 500);
	        }
	        private class MyGestureListener extends SimpleOnGestureListener {
	                
	            /** 滑動 */
	            @Override
	            public boolean onScroll(MotionEvent e1, MotionEvent e2,
	                    float distanceX, float distanceY) {
	                float mOldX = e1.getX(), mOldY = e1.getY();
	                int y = (int) e2.getRawY();
	                Display disp = getWindowManager().getDefaultDisplay();
	                int windowWidth = disp.getWidth();
	                int windowHeight = disp.getHeight();
	    
	                if (mOldX > windowWidth * 4.0 / 5)// 右邊滑動
	                    onVolumeSlide((mOldY - y) / windowHeight);
	                else if (mOldX < windowWidth / 5.0)// 左邊滑動
	                {
	                	nextFlag=true;
	                	f=(mOldY - y) / windowHeight;
	                    //onNextSlide((mOldY - y) / windowHeight);
	                }
	    
	                return super.onScroll(e1, e2, distanceX, distanceY);
	            }
	        }
	    
	        /** 定時隱藏 */
	        private   Handler mDismissHandler = new Handler() {
	            @Override
	            public void handleMessage(Message msg) {
	                tv_volume.setVisibility(View.GONE);
	            }
	        };
			private void onNextSlide(float f) {
				if(f>0)
					current++;
				else
					current--;
		    	if(current>=updateMan.localSaveName.size())
		    		current=0;
		    	if(current<0)
		    		current=updateMan.localSaveName.size()-1;
		    	play(); 
		    	
	            // 提示
	            tv_volume.setText(""+current+" "+updateMan.localSaveName.get(current));
                // 顯示
                tv_volume.setVisibility(View.VISIBLE);
			}
	        /**
	         * 滑動改變聲音大小
	         * 
	         * @param percent
	         */
	private void onVolumeSlide(float percent) {
		if (mVolume == -1) {
			mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
			if (mVolume < 0)
				mVolume = 0;
			// 顯示
			tv_volume.setVisibility(View.VISIBLE);
		}
	    
	            int index = (int) (percent * mMaxVolume) + mVolume;
	            if (index > mMaxVolume)
	                index = mMaxVolume;
	            else if (index < 0)
	                index = 0;
	    
	            // 變更聲音
	            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);	            
	            // 變更進度條
	            tv_volume.setText("音量:"+index*100/mMaxVolume+"%");
	        }
}
package com.example.video;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import com.trinet.util.NetHelper;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class UpdateManager {

	private UpdateCallback callback;
	private Context ctx;
    
	private int progress;  
	private Boolean hasNewVersion;
	private Boolean canceled;


	//存放更新文件的路徑
//	public static final String UPDATE_DOWNURL = "http://wjsou.com/dropzone/uploads/BluetoothChatFile.apk";
	//存放更新文件相應的版本說明路徑
	public static final String UPDATE_CHECKURL = "http://wjsou.com/dropzone/uploads/video_version.txt";
	public static final String updateDownUrlPre="http://wjsou.com/dropzone/uploads/";
//	public static String saveName;
	public List<String> needSaveName= new ArrayList<String>();
	public static List<String> localSaveName= new ArrayList<String>();
	public static final String CONFIG="config";  //配置文件
	//APK文件名
//	public static final String UPDATE_SAVENAME = "BluetoothChatFile.apk";
	//public static final String UPDATE_APKNAME = "update_test.apk";
	//public static final String UPDATE_VERJSON = "ver.txt";
	private static final int UPDATE_CHECKCOMPLETED = 1;
	 private static final int UPDATE_DOWNLOADING = 2; 
	 private static final int UPDATE_DOWNLOAD_ERROR = 3; 
	 private static final int UPDATE_DOWNLOAD_COMPLETED = 4; 
	 private static final int UPDATE_DOWNLOAD_CANCELED = 5;

	 //從服務器上下載apk存放文件夾
	 public static String savefolder = "/storage/emulated/0/xiaoying/";
	// private String savefolder = "/mnt/innerDisk/";
	 //private String savefolder = "/sdcard/";
		//public static final String SAVE_FOLDER =Storage. // "/mnt/innerDisk";
	public UpdateManager(Context context, UpdateCallback updateCallback) {
		ctx = context;
		callback = updateCallback;
		//savefolder = context.getFilesDir();
		canceled = false;
		readLocalSaveName();
	}
	private void readLocalSaveName() //讀出所有保存的文件名
	{
		// 讀取設置數據
		SharedPreferences sharedata1 = ctx.getSharedPreferences(CONFIG, 0);	
		for(int i=0;;i++)
		{
			String stringName = sharedata1.getString(String.valueOf(i), null);
			if(stringName==null)
			{
				break;
			}
			localSaveName.add(stringName);
			Log.i("localSaveName", stringName+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
		}
	}	
	public void checkUpdate() {		
		hasNewVersion = false;
		new Thread(){
			@Override
			public void run() {
				Log.i("@@@@@", ">>>>>>>>>>>>>>>>>>>>>>>>>>>getServerVerCode() ");
				try {
					String verjson = NetHelper.httpStringGet(UPDATE_CHECKURL);
					Log.i("@@@@", verjson
							+ "**************************************************");
					JSONArray array = new JSONArray(verjson);
					if(array.length()>0){
						for(int i=0;i<array.length();i++) {
							
							JSONObject obj = array.getJSONObject(i);
							try {
								String name=obj.getString("Name");
								Log.i("Name", name+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
//								if(i<localSaveName.size()&& !localSaveName.get(i).equals(name))
//								{
//									//更新原位置文件,完成後刪除原位置的不同名文件
//									//position=i;
//									
//								}
								if(!localSaveName.contains(name))  //不存在,就需要保存
								{
									needSaveName.add(name);
									Log.i("needSaveName", name+ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
									hasNewVersion = true;
								}							
							} catch (Exception e) {								
							}
						}					
					}
				} catch (Exception e) {
					Log.e("update", e.getMessage());
				}
				updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
			};
			// ***************************************************************
		}.start();

	}

	public void update() { //下載完成一個後,加入保存到本地庫中,刪除需要下載列表的已經下載成功的.
		SharedPreferences.Editor sharedata = ctx.getSharedPreferences(CONFIG, 0).edit();
		sharedata.putString(String.valueOf(localSaveName.size()),needSaveName.get(0));
		sharedata.commit();
		localSaveName.add(needSaveName.get(0));		
	
		needSaveName.remove(needSaveName.get(0));
	}

	// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	public void downloadPackage() 
	{
		
		
		new Thread() {			
			 @Override  
		        public void run() {  
		            try {  
		                URL url = new URL(updateDownUrlPre+needSaveName.get(0));  
		              
		                HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
		                conn.connect();  
		                int length = conn.getContentLength();  
		                InputStream is = conn.getInputStream();  
		                  
		                File filefolder = new File(savefolder);  
		              //判斷文件夾是否存在,如果不存在就創建,否則不創建  
		                if (!filefolder.exists()) {  		         
		                	filefolder.mkdirs();  
		                }  
		                File File = new File(savefolder,needSaveName.get(0));
		                
		                
		                if(File.exists())
		                {
		                	
		                	File.delete();
		                }
		                
		                
		                FileOutputStream fos = new FileOutputStream(File);  
		                 
		                int count = 0;  
		                byte buf[] = new byte[512];  
		                  
		                do{  
		                	
		                    int numread = is.read(buf);  
		                    count += numread;  
		                    progress =(int)(((float)count / length) * 100);  
		                   
		                    updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOADING)); 
		                    if(numread <= 0){      
		                        
		                    	updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
		                        break;  
		                    }  
		                    fos.write(buf,0,numread);  
		                }while(!canceled);  
		                if(canceled)
		                {
		                	updateHandler.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
		                }
		                fos.close();  
		                is.close();  
		            } catch (MalformedURLException e) {  
		                e.printStackTrace(); 
		                
		                updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
		            } catch(IOException e){  
		                e.printStackTrace();  
		                
		                updateHandler.sendMessage(updateHandler.obtainMessage(UPDATE_DOWNLOAD_ERROR,e.getMessage()));
		            }  
		              
		        } 
		}.start();
	}

	public void cancelDownload()
	{
		canceled = true;
	}
	
	Handler updateHandler = new Handler() 
	{
		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {
			case UPDATE_CHECKCOMPLETED:
				if(hasNewVersion)
					callback.checkUpdateCompleted(hasNewVersion,needSaveName.get(0));
				break;
			case UPDATE_DOWNLOADING:
				
				callback.downloadProgressChanged(progress);
				break;
			case UPDATE_DOWNLOAD_ERROR:
				
				callback.downloadCompleted(false, msg.obj.toString());
				break;
			case UPDATE_DOWNLOAD_COMPLETED:
				
				callback.downloadCompleted(true, "");
				break;
			case UPDATE_DOWNLOAD_CANCELED:
				
				callback.downloadCanceled();
			default:
				break;
			}
		}
	};

	public interface UpdateCallback {
		public void checkUpdateCompleted(Boolean hasUpdate,	CharSequence updateInfo);

		public void downloadProgressChanged(int progress);
		public void downloadCanceled();
		public void downloadCompleted(Boolean sucess, CharSequence errorMsg);
	}

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章