抓取的是芒果tv官方的api,理由永久可用
补上一张播放图
界面随便写了一下,一共分为三次解析,利用芒果tv的影片ID,最终解析出来的是m3u8的地址,播放器我是用的Vitamio播放器,
贴一下MainActivity的代码
1 package com.macernow.djstava.djmediaplayer; 2 3 import android.content.Intent; 4 import android.os.Bundle; 5 import android.os.Environment; 6 import android.support.v7.app.AppCompatActivity; 7 import android.support.v7.widget.GridLayoutManager; 8 import android.util.Log; 9 import android.view.Menu; 10 import android.view.MenuItem; 11 import android.view.View; 12 import android.view.WindowManager; 13 import android.widget.AdapterView; 14 import android.widget.ImageView; 15 import android.widget.ListView; 16 import android.widget.TextView; 17 import android.widget.Toast; 18 19 import com.android.volley.Request; 20 import com.android.volley.RequestQueue; 21 import com.android.volley.Response; 22 import com.android.volley.VolleyError; 23 import com.android.volley.toolbox.StringRequest; 24 import com.android.volley.toolbox.Volley; 25 26 import org.json.JSONArray; 27 import org.json.JSONObject; 28 29 import java.io.File; 30 import java.util.ArrayList; 31 import java.util.List; 32 33 public class MainActivity extends AppCompatActivity { 34 35 private SwipeRecyclerView listView; 36 private int path= 0; 37 private int a= 0; 38 private RequestQueue requestQueue; 39 private ArrayList<NeBss> mDatas = new ArrayList<>(); 40 private ArrayList<NeBss> newslist = new ArrayList<>(); 41 private YingShiAdapter yinshiadapter; 42 private String titles; 43 44 45 @Override 46 protected void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 setContentView(R.layout.activity_main); 49 requestQueue = Volley.newRequestQueue(this); 50 Toast.makeText(this, "列表滑到底部,请手动点击切换下一页", Toast.LENGTH_LONG).show(); 51 //初始化组件 52 listView = (SwipeRecyclerView)findViewById(R.id.lv_id); 53 //下一页 54 TextView textView = (TextView) findViewById(R.id.tv_xia); 55 textView.setOnClickListener(new View.OnClickListener() { 56 @Override 57 public void onClick(View v) { 58 path = path+1; 59 a++; 60 gengduo(0,a); 61 } 62 }); 63 //排列方式 64 listView.getRecyclerView().setLayoutManager(new GridLayoutManager(MainActivity.this, 3)); 65 listView.getSwipeRefreshLayout() 66 .setColorSchemeColors(getResources().getColor(R.color.yellow)); 67 //禁止下拉刷新 68 listView.setRefreshEnable(true); 69 //禁止加载更多 70 listView.setLoadMoreEnable(true); 71 //触发刚发 72 listView.setOnLoadListener(new SwipeRecyclerView.OnLoadListener(){ 73 //刷新数据 74 @Override 75 public void onRefresh() { 76 } 77 //加载更多 78 @Override 79 public void onLoadMore() { 80 // path = path+1; 81 a++; 82 gengduo(0,a); 83 } 84 }); 85 //开始加载 86 kaishi(); 87 } 88 89 /** 90 * 第一次加载网络 91 */ 92 private void kaishi() { 93 StringRequest strq = new StringRequest(Request.Method.GET, getUrls(path), new Response.Listener<String>() { 94 @Override 95 public void onResponse(String response) { 96 try { 97 //解析json 98 newslist = getList(response); 99 yinshiadapter = new YingShiAdapter(MainActivity.this,newslist); 100 listView.setAdapter(yinshiadapter); 101 //点击事件 102 yinshiadapter.setIjieKOu(new IjieKOu() { 103 @Override 104 public void setDianJi(int i) { 105 //拿到视频ID进行第二次解析 106 getLissUrl(newslist.get(i).videoId); 107 } 108 }); 109 } catch (Exception e) { 110 e.printStackTrace(); 111 } 112 } 113 }, new Response.ErrorListener() { 114 @Override 115 public void onErrorResponse(VolleyError error) { 116 117 } 118 }); 119 requestQueue.add(strq); 120 } 121 /** 122 * 更多加载网络 123 */ 124 private void gengduo(int i,int a) { 125 String url; 126 if(i == 1){ 127 url = getUrls(path); 128 }else{ 129 url = getYUrls(path,a); 130 } 131 StringRequest strq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { 132 @Override 133 public void onResponse(String response) { 134 try { 135 newslist = getList(response); 136 yinshiadapter.setStringList(newslist); 137 } catch (Exception e) { 138 e.printStackTrace(); 139 } 140 } 141 }, new Response.ErrorListener() { 142 @Override 143 public void onErrorResponse(VolleyError error) { 144 145 } 146 }); 147 requestQueue.add(strq); 148 } 149 150 /** 151 * 第二次请求网络 152 * @param videoId 153 */ 154 private void getLissUrl(String videoId) { 155 StringRequest strq = new StringRequest(Request.Method.GET, getUrlsss(videoId), new Response.Listener<String>() { 156 @Override 157 public void onResponse(String response) { 158 try { 159 String url = getUrl(response); 160 //拼接出来地址,进行第三次网络请求 161 getZhenUrl(url); 162 } catch (Exception e) { 163 e.printStackTrace(); 164 } 165 } 166 }, new Response.ErrorListener() { 167 @Override 168 public void onErrorResponse(VolleyError error) { 169 170 } 171 }); 172 requestQueue.add(strq); 173 } 174 175 /** 176 * 第三次请求网络数据 177 * @param url 178 */ 179 private void getZhenUrl(String url) { 180 StringRequest strq = new StringRequest(Request.Method.GET, getUrlssss(url), new Response.Listener<String>() { 181 @Override 182 public void onResponse(String response) { 183 try { 184 //得到最终结果,解析出来url,传递给播放页面 185 JSONObject js = new JSONObject(response); 186 String url = js.getString("info"); 187 Intent intent = new Intent(MainActivity.this,VitamioVideoViewActivity.class); 188 intent.putExtra("movieUrl",url); 189 startActivity(intent); 190 } catch (Exception e) { 191 e.printStackTrace(); 192 } 193 } 194 }, new Response.ErrorListener() { 195 @Override 196 public void onErrorResponse(VolleyError error) { 197 198 } 199 }); 200 requestQueue.add(strq); 201 } 202 203 204 205 206 207 @Override 208 public boolean onCreateOptionsMenu(Menu menu) { 209 // Inflate the menu; this adds items to the action bar if it is present. 210 getMenuInflater().inflate(R.menu.menu_main, menu); 211 return true; 212 } 213 214 @Override 215 public boolean onOptionsItemSelected(MenuItem item) { 216 // Handle action bar item clicks here. The action bar will 217 // automatically handle clicks on the Home/Up button, so long 218 // as you specify a parent activity in AndroidManifest.xml. 219 int id = item.getItemId(); 220 221 //noinspection SimplifiableIfStatement 222 if (id == R.id.action_settings) { 223 return true; 224 } 225 226 return super.onOptionsItemSelected(item); 227 } 228 229 /** 230 * 列表api 231 * @param path 232 * @return 233 */ 234 public static String getUrls(int path){ 235 String url = "http://mobile.api.hunantv.com/list?userId=&order="+path+"&types=all&pageCount=1.0&pageSize=500&typeId=3"; 236 return url; 237 } 238 239 public static String getYUrls(int path,int a){ 240 String url = "http://mobile.api.hunantv.com/list?userId=&order="+path+"&types=all&pageCount="+a+".0&pageSize=800&typeId=3"; 241 return url; 242 } 243 244 /** 245 * 解析信息 246 * @param path 247 * @return 248 */ 249 public static String getUrlsss(String path){ 250 String url = "http://pcweb.api.mgtv.com/player/video?video_id="+path; 251 return url; 252 } 253 254 /** 255 * 得到真实地址 256 * @param path 257 * @return 258 */ 259 public static String getUrlssss(String path){ 260 String url = "http://disp.titan.mgtv.com/"+path; 261 return url; 262 } 263 264 265 /** 266 * 解析第一次网络请求的数据 267 * @param response 268 * @return 269 * @throws Exception 270 */ 271 public ArrayList<NeBss> getList(String response) throws Exception { 272 try { 273 JSONObject json = new JSONObject(response); 274 JSONArray jsonArray = json.getJSONArray("data"); 275 for (int i = 0; i < jsonArray.length(); i++) { 276 JSONObject jsonObject = jsonArray.getJSONObject(i); 277 String title = jsonObject.getString("name"); 278 String str = jsonObject.getString("image"); 279 String videoId = jsonObject.getString("videoId"); 280 NeBss info = new NeBss(title,str,videoId); 281 mDatas.add(info); 282 } 283 } catch (Exception e) { 284 285 } 286 return mDatas; 287 } 288 289 /** 290 * 第二次网络请求数据 291 * @param response 292 * @return 293 * @throws Exception 294 */ 295 public String getUrl(String response) throws Exception { 296 try { 297 JSONObject json = new JSONObject(response); 298 JSONObject jsonArray = json.getJSONObject("data"); 299 JSONArray jsonArrays = jsonArray.getJSONArray("stream"); 300 for (int i = 0; i < jsonArray.length(); i++) { 301 JSONObject jsonArray2 = jsonArrays.getJSONObject(i); 302 titles = jsonArray2.getString("url"); 303 } 304 } catch (Exception e) { 305 306 } 307 return titles; 308 } 309 }
activity_main.xml
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:background="@drawable/music_background" 5 android:orientation="vertical" > 6 7 <TextView 8 android:id="@+id/textview_title" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:layout_gravity="center" 12 android:gravity="center" 13 android:singleLine="true" 14 android:text="@string/movieList" 15 android:textColor="@color/white" 16 android:textSize="30sp" /> 17 18 19 20 <TextView android:text="下一页" 21 android:id="@+id/tv_xia" 22 android:layout_width="wrap_content" 23 android:textColor="@color/white" 24 android:textSize="30sp" android:layout_alignParentRight="true" 25 android:layout_height="wrap_content" /> 26 27 28 <TextView android:text="上一页" 29 android:layout_width="wrap_content" 30 android:textColor="@color/white" 31 android:textSize="30sp" 32 android:layout_height="wrap_content" /> 33 <View android:layout_below="@+id/textview_title" 34 android:layout_width="wrap_content" 35 android:layout_height="1dp" 36 android:id="@+id/ssss" 37 android:background="@drawable/single_line" /> 38 39 40 <com.macernow.djstava.djmediaplayer.SwipeRecyclerView 41 android:id="@+id/lv_id" 42 android:layout_below="@+id/ssss" 43 android:layout_width="match_parent" 44 android:layout_height="wrap_content" 45 android:visibility="visible" 46 /> 47 <Button android:id="@+id/buttid" 48 android:text="下一页" android:layout_below="@+id/lv_id" 49 android:layout_width="match_parent" 50 android:layout_height="wrap_content" /> 51 </RelativeLayout>
播放页面代码
1 package com.macernow.djstava.djmediaplayer; 2 3 import android.app.AlertDialog; 4 import android.content.Context; 5 import android.content.DialogInterface; 6 import android.content.Intent; 7 import android.media.AudioManager; 8 import android.net.Uri; 9 import android.os.Bundle; 10 import android.os.Handler; 11 import android.os.Message; 12 import android.support.v7.app.AppCompatActivity; 13 import android.view.Display; 14 import android.view.GestureDetector; 15 import android.view.KeyEvent; 16 import android.view.Menu; 17 import android.view.MenuItem; 18 import android.view.MotionEvent; 19 import android.view.View; 20 import android.view.ViewGroup; 21 import android.view.WindowManager; 22 import android.widget.ImageView; 23 import android.widget.Toast; 24 25 import io.vov.vitamio.LibsChecker; 26 import io.vov.vitamio.MediaPlayer; 27 import io.vov.vitamio.widget.MediaController; 28 import io.vov.vitamio.widget.VideoView; 29 30 public class VitamioVideoViewActivity extends AppCompatActivity { 31 32 private VideoView videoView; 33 private Intent intent; 34 private String movieUrl; 35 private MediaController mediaController; 36 private AudioManager audioManager; 37 private GestureDetector gestureDetector; 38 private ImageView mOperationBg, mOperationPercent; 39 private long currentPosition, duration; 40 private View mVolumeBrightnessLayout; 41 42 /*最大声音*/ 43 private int maxVolume; 44 45 /*当前声音*/ 46 private int currentVolume = -1; 47 48 /**/ 49 50 @Override 51 protected void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 if (!LibsChecker.checkVitamioLibs(this)) 54 return; 55 setContentView(R.layout.activity_vitamio_video_view); 56 Toast.makeText(this, "视频正在加载,请手动点击两下屏幕", Toast.LENGTH_SHORT).show(); 57 /* 58 * 去屏保 59 * */ 60 getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 61 //初始化组件 62 videoView = (VideoView) this.findViewById(R.id.surface_view); 63 mVolumeBrightnessLayout = findViewById(R.id.operation_volume); 64 mOperationBg = (ImageView) findViewById(R.id.operation_bg); 65 mOperationPercent = (ImageView) findViewById(R.id.operation_percent); 66 //接收传递过来的值 67 intent = getIntent(); 68 movieUrl = intent.getStringExtra("movieUrl"); 69 mediaController = new MediaController(this); 70 //设置参数 71 audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 72 maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 73 //设置参数 74 if (!movieUrl.isEmpty()) { 75 if (movieUrl.startsWith("http:")) { 76 videoView.setVideoURI(Uri.parse(movieUrl)); 77 } else { 78 videoView.setVideoPath(movieUrl); 79 } 80 //设置参数 81 videoView.setVideoLayout(VideoView.VIDEO_LAYOUT_STRETCH, 0); 82 videoView.setMediaController(mediaController); 83 videoView.requestFocus(); 84 85 videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 86 @Override 87 public void onPrepared(MediaPlayer mp) { 88 mp.setPlaybackSpeed(1.0f); 89 duration = mp.getDuration(); 90 } 91 }); 92 93 videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 94 @Override 95 public void onCompletion(MediaPlayer mp) { 96 Toast.makeText(VitamioVideoViewActivity.this, R.string.video_finish, Toast.LENGTH_SHORT).show(); 97 finish(); 98 } 99 }); 100 101 videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { 102 @Override 103 public boolean onError(MediaPlayer mp, int what, int extra) { 104 new AlertDialog.Builder(VitamioVideoViewActivity.this).setTitle(R.string.video_error) 105 .setPositiveButton(R.string.video_error_yes, new DialogInterface.OnClickListener() { 106 @Override 107 public void onClick(DialogInterface dialog, int which) { 108 finish(); 109 } 110 }) 111 .show(); 112 113 return true; 114 } 115 }); 116 } else { 117 Toast.makeText(VitamioVideoViewActivity.this, R.string.no_such_movie, Toast.LENGTH_SHORT).show(); 118 } 119 120 gestureDetector = new GestureDetector(this, new CustomGestureListener()); 121 } 122 123 @Override 124 public boolean onTouchEvent(MotionEvent event) { 125 if (gestureDetector.onTouchEvent(event)) { 126 return true; 127 } 128 129 switch (event.getAction() & MotionEvent.ACTION_MASK) { 130 case MotionEvent.ACTION_UP: 131 endGesture(); 132 break; 133 } 134 135 return super.onTouchEvent(event); 136 } 137 138 private void endGesture() { 139 currentVolume = -1; 140 141 mDismissHandler.removeMessages(0); 142 mDismissHandler.sendEmptyMessageDelayed(0, 500); 143 } 144 145 private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener { 146 147 /* 148 * 双击操作 149 * */ 150 @Override 151 public boolean onDoubleTap(MotionEvent e) { 152 if (videoView.isPlaying()) { 153 videoView.pause(); 154 } else { 155 videoView.start(); 156 } 157 158 return super.onDoubleTap(e); 159 } 160 161 @Override 162 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 163 164 //上下滑动 165 if (Math.abs(distanceY) / Math.abs(distanceX) > 3) { 166 float mOldY = e1.getY(); 167 int y = (int) e2.getRawY(); 168 Display disp = getWindowManager().getDefaultDisplay(); 169 int windowHeight = disp.getHeight(); 170 171 onVolumeSlide((mOldY - y) / windowHeight); 172 173 } 174 175 return super.onScroll(e1, e2, distanceX, distanceY); 176 } 177 178 /* 179 * 滑动操作 180 * */ 181 @Override 182 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 183 184 currentPosition = videoView.getCurrentPosition(); 185 186 /*向左滑*/ 187 if (e1.getX() - e2.getX() > 120) { 188 189 if (currentPosition < 10000) { 190 currentPosition = 0; 191 videoView.seekTo(currentPosition); 192 } else { 193 videoView.seekTo(currentPosition - 10000); 194 } 195 196 } else if (e2.getX() - e1.getX() > 120) { 197 /*向右滑*/ 198 if (currentPosition + 10000 > duration) { 199 currentPosition = duration; 200 videoView.seekTo(currentPosition); 201 } else { 202 videoView.seekTo(currentPosition + 10000); 203 } 204 205 } 206 207 return super.onFling(e1, e2, velocityX, velocityY); 208 } 209 } 210 211 /* 212 * 定时隐藏 213 * */ 214 private Handler mDismissHandler = new Handler() { 215 @Override 216 public void handleMessage(Message msg) { 217 mVolumeBrightnessLayout.setVisibility(View.GONE); 218 } 219 }; 220 221 /** 222 * 滑动改变声音大小 223 */ 224 private void onVolumeSlide(float percent) { 225 226 if (currentVolume == -1) { 227 currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 228 if (currentVolume < 0) 229 currentVolume = 0; 230 231 // 显示 232 mOperationBg.setImageResource(R.drawable.video_volumn_bg); 233 mVolumeBrightnessLayout.setVisibility(View.VISIBLE); 234 } 235 236 int value = currentVolume + (int) (percent * maxVolume); 237 if (value > maxVolume) { 238 value = maxVolume; 239 } else if (value < 0) { 240 value = 0; 241 } 242 243 // 变更声音 244 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, 0); 245 246 // 变更进度条 247 ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams(); 248 lp.width = findViewById(R.id.operation_full).getLayoutParams().width * value / maxVolume; 249 mOperationPercent.setLayoutParams(lp); 250 } 251 252 @Override 253 public boolean onKeyDown(int keyCode, KeyEvent event) { 254 switch (keyCode) { 255 case KeyEvent.KEYCODE_BACK: 256 new AlertDialog.Builder(VitamioVideoViewActivity.this).setMessage(R.string.alertdialog_message) 257 .setTitle(R.string.alertdialog_title) 258 .setCancelable(false) 259 .setPositiveButton(R.string.alertdialog_yes, new DialogInterface.OnClickListener() { 260 @Override 261 public void onClick(DialogInterface dialog, int which) { 262 finish(); 263 } 264 }) 265 .setNegativeButton(R.string.alertdialog_no, new DialogInterface.OnClickListener() { 266 @Override 267 public void onClick(DialogInterface dialog, int which) { 268 dialog.dismiss(); 269 } 270 }).show(); 271 break; 272 273 default: 274 break; 275 } 276 277 return super.onKeyDown(keyCode, event); 278 } 279 280 @Override 281 protected void onPause() { 282 super.onPause(); 283 284 if (videoView != null) { 285 videoView.pause(); 286 } 287 } 288 289 @Override 290 protected void onResume() { 291 super.onResume(); 292 293 if (videoView != null) { 294 videoView.resume(); 295 } 296 } 297 298 @Override 299 protected void onDestroy() { 300 super.onDestroy(); 301 302 if (videoView != null) { 303 videoView.stopPlayback(); 304 } 305 } 306 307 @Override 308 public boolean onCreateOptionsMenu(Menu menu) { 309 // Inflate the menu; this adds items to the action bar if it is present. 310 getMenuInflater().inflate(R.menu.menu_vitamio_video_view, menu); 311 return true; 312 } 313 314 @Override 315 public boolean onOptionsItemSelected(MenuItem item) { 316 // Handle action bar item clicks here. The action bar will 317 // automatically handle clicks on the Home/Up button, so long 318 // as you specify a parent activity in AndroidManifest.xml. 319 int id = item.getItemId(); 320 321 //noinspection SimplifiableIfStatement 322 if (id == R.id.action_settings) { 323 return true; 324 } 325 326 return super.onOptionsItemSelected(item); 327 } 328 }
注:播放页面,没有什么注释,因为用的是第三方库,
xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical"> 6 7 <io.vov.vitamio.widget.VideoView 8 android:id="@+id/surface_view" 9 android:layout_width="fill_parent" 10 android:layout_height="fill_parent" 11 android:layout_centerHorizontal="true" 12 android:layout_centerVertical="true" /> 13 14 <FrameLayout 15 android:id="@+id/operation_volume" 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" 18 android:layout_centerInParent="true" 19 android:background="#00000000" 20 android:orientation="horizontal" 21 android:padding="0dip" 22 android:visibility="invisible"> 23 24 <ImageView 25 android:id="@+id/operation_bg" 26 android:layout_width="wrap_content" 27 android:layout_height="wrap_content" 28 android:layout_gravity="center" 29 android:src="@drawable/video_volumn_bg" /> 30 31 <FrameLayout 32 android:layout_width="wrap_content" 33 android:layout_height="wrap_content" 34 android:layout_gravity="bottom|center_horizontal" 35 android:paddingBottom="25dip"> 36 37 <ImageView 38 android:id="@+id/operation_full" 39 android:layout_width="94dip" 40 android:layout_height="wrap_content" 41 android:layout_gravity="left" 42 android:src="@drawable/video_num_bg" /> 43 44 <ImageView 45 android:id="@+id/operation_percent" 46 android:layout_width="0dip" 47 android:layout_height="wrap_content" 48 android:layout_gravity="left" 49 android:scaleType="matrix" 50 android:src="@drawable/video_num_front" /> 51 </FrameLayout> 52 </FrameLayout> 53 54 </RelativeLayout>
这样就写完了,
附上代码下载地址链接:http://pan.baidu.com/s/1pKGK25l 密码:pa63
apk下载地址 链接:http://pan.baidu.com/s/1hrCUX1M 密码:xlnc
依赖的是vitamio,去官方下一个就好,我就不上传了,