仿抖音安卓apk演示:https://pan.baidu.com/s/1yKgoInXGGNe4BuS1WsGElQ
视频可以批量上传:http://6.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;i0)
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 needSaveName= new ArrayList();
public static List localSaveName= new ArrayList();
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