i.putExtra(“command”, “pause”);
mContext.sendBroadcast(i);
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(mPreparedListener);
mediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
isPrepared = false;
Log.v(TAG, “reset duration to -1 in openVideo”);
mDuration = -1;
mediaPlayer.setOnCompletionListener(mCompletionListener);
mediaPlayer.setOnErrorListener(mErrorListener);
mediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
currentBufferPercentage = 0;
mediaPlayer.setDataSource(mContext, mUri);
mediaPlayer.setDisplay(mSurfaceHolder);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setScreenOnWhilePlaying(true);
mediaPlayer.prepareAsync();
attachMediaController();
} catch (IOException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
return;
} catch (IllegalArgumentException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
return;
}
}
public void setMediaController(MediaController controller) {
if (mediaController != null) {
mediaController.hide();
}
mediaController = controller;
attachMediaController();
}
private void attachMediaController() {
if (mediaPlayer != null && mediaController != null) {
mediaController.setMediaPlayer(this);
View anchorView = this.getParent() instanceof View ?
(View) this.getParent() : this;
mediaController.setAnchorView(anchorView);
mediaController.setEnabled(isPrepared);
}
}
MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
new MediaPlayer.OnVideoSizeChangedListener() {
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
videoWidth = mp.getVideoWidth();
videoHeight = mp.getVideoHeight();
if (mMyChangeLinstener != null) {
mMyChangeLinstener.doMyThings();
}
if (videoWidth != 0 && videoHeight != 0) {
getHolder().setFixedSize(videoWidth, videoHeight);
}
}
};
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// briefly show the mediacontroller
isPrepared = true;
if (myOnPreparedListener != null) {
myOnPreparedListener.onPrepared(mediaPlayer);
}
if (mediaController != null) {
mediaController.setEnabled(true);
}
videoWidth = mp.getVideoWidth();
videoHeight = mp.getVideoHeight();
if (videoWidth != 0 && videoHeight != 0) {
//Log.i(“@@@@”, “video size: " + mVideoWidth +”/"+ mVideoHeight);
getHolder().setFixedSize(videoWidth, videoHeight);
if (surfaceWidth == videoWidth && surfaceHeight == videoHeight) {
// We didn’t actually change the size (it was already at the size
// we need), so we won’t get a “surface changed” callback, so
// start the video here instead of in the callback.
if (seekWhenPrepared != 0) {
mediaPlayer.seekTo(seekWhenPrepared);
seekWhenPrepared = 0;
}
if (startWhenPrepared) {
mediaPlayer.start();
startWhenPrepared = false;
if (mediaController != null) {
mediaController.show();
}
} else if (!isPlaying() &&
(seekWhenPrepared != 0 || getCurrentPosition() > 0)) {
if (mediaController != null) {
// Show the media controls when we’re paused into a video and make 'em stick.
mediaController.show(0);
}
}
}
} else {
// We don’t know the video size yet, but should start anyway.
// The video size might be reported to us later.
if (seekWhenPrepared != 0) {
mediaPlayer.seekTo(seekWhenPrepared);
seekWhenPrepared = 0;
}
if (startWhenPrepared) {
mediaPlayer.start();
startWhenPrepared = false;
}
}
}
};
private OnCompletionListener mCompletionListener =
new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
if (mediaController != null) {
mediaController.hide();
}
if (myOnCompletionListener != null) {
myOnCompletionListener.onCompletion(mediaPlayer);
}
}
};
private OnErrorListener mErrorListener =
new OnErrorListener() {
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
Log.d(TAG, "Error: " + framework_err + “,” + impl_err);
if (mediaController != null) {
mediaController.hide();
}
/* If an error handler has been supplied, use it and finish. */
if (myOnErrorListener != null) {
if (myOnErrorListener.onError(mediaPlayer, framework_err, impl_err)) {
return true;
}
}
/* Otherwise, pop up an error dialog so the user knows that
-
something bad has happened. Only try and pop up the dialog
-
if we’re attached to a window. When we’re going away and no
-
longer have a window, don’t bother showing the user an error.
*/
if (getWindowToken() != null) {
Resources r = mContext.getResources();
int messageId;
/* if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
} else {
messageId = com.android.internal.R.string.VideoView_error_text_unknown;
}
new AlertDialog.Builder(mContext)
.setTitle(com.android.internal.R.string.VideoView_error_title)
.setMessage(messageId)
.setPositiveButton(com.android.internal.R.string.VideoView_error_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
If we get here, there is no onError listener, so
- at least inform them that the video is over.
if (mOnCompletionListener != null) {
mOnCompletionListener.onCompletion(mMediaPlayer);
}
}
})
.setCancelable(false)
.show();*/
}
return true;
}
};
private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
new MediaPlayer.OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
currentBufferPercentage = percent;
}
};
/**
-
Register a callback to be invoked when the media file
-
is loaded and ready to go.
-
@param l The callback that will be run
*/
public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
myOnPreparedListener = l;
}
/**
-
Register a callback to be invoked when the end of a media file
-
has been reached during playback.
-
@param l The callback that will be run
*/
public void setOnCompletionListener(OnCompletionListener l) {
myOnCompletionListener = l;
}
/**
-
Register a callback to be invoked when an error occurs
-
during playback or setup. If no listener is specified,
-
or if the listener returned false, VideoView will inform
-
the user of any errors.
-
@param l The callback that will be run
*/
public void setOnErrorListener(OnErrorListener l) {
myOnErrorListener = l;
}
SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
public void surfaceChanged(SurfaceHolder holder, int format,
int w, int h) {
surfaceWidth = w;
surfaceHeight = h;
if (mediaPlayer != null && isPrepared && videoWidth == w && videoHeight == h) {
if (seekWhenPrepared != 0) {
mediaPlayer.seekTo(seekWhenPrepared);
seekWhenPrepared = 0;
}
mediaPlayer.start();
if (mediaController != null) {
mediaController.show();
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
mSurfaceHolder = holder;
openVideo();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// after we return from this we can’t use the surface any more
mSurfaceHolder = null;
if (mediaController != null) mediaController.hide();
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}
};
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isPrepared && mediaPlayer != null && mediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
if (isPrepared && mediaPlayer != null && mediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (isPrepared &&
keyCode != KeyEvent.KEYCODE_BACK &&
keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
keyCode != KeyEvent.KEYCODE_MENU &&
keyCode != KeyEvent.KEYCODE_CALL &&
keyCode != KeyEvent.KEYCODE_ENDCALL &&
mediaPlayer != null &&
mediaController != null) {
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
if (mediaPlayer.isPlaying()) {
pause();
mediaController.show();
} else {
start();
mediaController.hide();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
&& mediaPlayer.isPlaying()) {
pause();
mediaController.show();
} else {
toggleMediaControlsVisiblity();
}
}
return super.onKeyDown(keyCode, event);
}
private void toggleMediaControlsVisiblity() {
if (mediaController.isShowing()) {
mediaController.hide();
} else {
mediaController.show();
}
}
public void start() {
if (mediaPlayer != null && isPrepared) {
mediaPlayer.start();
startWhenPrepared = false;
} else {
startWhenPrepared = true;
}
}
public void pause() {
if (mediaPlayer != null && isPrepared) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
startWhenPrepared = false;
}
public int getDuration() {
if (mediaPlayer != null && isPrepared) {
if (mDuration > 0) {
return mDuration;
}
mDuration = mediaPlayer.getDuration();
return mDuration;
}
mDuration = -1;
return mDuration;
}
public int getCurrentPosition() {
if (mediaPlayer != null && isPrepared) {
return mediaPlayer.getCurrentPosition();
}
return 0;
}
public void seekTo(int msec) {
if (mediaPlayer != null && isPrepared) {
mediaPlayer.seekTo(msec);
} else {
seekWhenPrepared = msec;
}
}
public boolean isPlaying() {
if (mediaPlayer != null && isPrepared) {
return mediaPlayer.isPlaying();
}
return false;
}
public int getBufferPercentage() {
if (mediaPlayer != null) {
return currentBufferPercentage;
}
return 0;
}
@Override
public boolean canPause() {
return false;
}
@Override
public boolean canSeekBackward() {
return false;
}
@Override
public boolean canSeekForward() {
return false;
}
@Override
public int getAudioSessionId() {
return 0;
}
}
VolumeView:
package com.tchip.autoplayer.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.media.AudioManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.tchip.autoplayer.R;
public class VolumeView extends View {
public final static String TAG = “SoundView”;
private Context context;
/**
- 音量条高亮
*/
private Bitmap bitmapVolumeLineOn;
private Bitmap bitmapVolumeLineOff;
private int bitmapWidth, bitmapHeight;
private int index;
private OnVolumeChangedListener mOnVolumeChangedListener;
private final static int HEIGHT = 11;
public final static int MY_HEIGHT = 163;
public final static int MY_WIDTH = 44;
public interface OnVolumeChangedListener {
public void setYourVolume(int index);
}
public void setOnVolumeChangeListener(OnVolumeChangedListener l) {
mOnVolumeChangedListener = l;
}
public VolumeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
context = context;
init();
}
public VolumeView(Context context, AttributeSet attrs) {
super(context, attrs);
context = context;
init();
}
public VolumeView(Context context) {
super(context);
context = context;
init();
}
private void init() {
bitmapVolumeLineOn = BitmapFactory.decodeResource(context.getResources(),
R.drawable.volume_line_on);
bitmapVolumeLineOff = BitmapFactory.decodeResource(context.getResources(),
R.drawable.volume_line_off);
bitmapWidth = bitmapVolumeLineOn.getWidth();
bitmapHeight = bitmapVolumeLineOn.getHeight();
//setIndex(5);
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
setIndex(am.getStreamVolume(AudioManager.STREAM_MUSIC));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
int n = y * 15 / MY_HEIGHT;
setIndex(15 - n);
Log.d(TAG, "setIndex: " + (15 - n));
return true;
}
@Override
protected void onDraw(Canvas canvas) {
int reverseIndex = 15 - index;
for (int i = 0; i != reverseIndex; ++i) {
canvas.drawBitmap(bitmapVolumeLineOff, new Rect(0, 0, bitmapWidth, bitmapHeight),
new Rect(0, i * HEIGHT, bitmapWidth, i * HEIGHT + bitmapHeight), null);
}
for (int i = reverseIndex; i != 15; ++i) {
canvas.drawBitmap(bitmapVolumeLineOn, new Rect(0, 0, bitmapWidth, bitmapHeight),
new Rect(0, i * HEIGHT, bitmapWidth, i * HEIGHT + bitmapHeight), null);
}
super.onDraw(canvas);
}
private void setIndex(int n) {
if (n > 15) {
n = 15;
} else if (n < 0) {
n = 0;
}
if (index != n) {
index = n;
if (mOnVolumeChangedListener != null) {
mOnVolumeChangedListener.setYourVolume(n);
}
}
invalidate();
}
}
VideoPlayerActivity:
package com.tchip.autoplayer;
import java.io.File;
import java.io.FileFilter;
import java.util.LinkedList;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue.IdleHandler;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import com.tchip.autoplayer.model.VideoInfo;
import com.tchip.autoplayer.view.VolumeView;
import com.tchip.autoplayer.view.VideoView;
public class VideoPlayerActivity extends Activity {
private final static String TAG = “VideoPlayerActivity”;
private boolean isOnline = false;
private boolean isChangedVideo = false;
public static LinkedList playList = new LinkedList();
private Uri videoListUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
private static int position;
private static boolean backFromAD = false;
private int playedTime;
/**
- 视频视图
*/
private VideoView videoView;
private SeekBar seekBar;
/**
- 视频总时间
*/
private TextView textTimeTotal;
/**
- 已播放时间
*/
private TextView textTimePlay;
private GestureDetector mGestureDetector = null;
private AudioManager mAudioManager = null;
private int maxVolume = 0;
private int currentVolume = 0;
/**
- 视频列表按钮
*/
private ImageButton btnList;
/**
- 上一部按钮
*/
private ImageButton btnPrevious;
/**
- 播放/暂停
*/
private ImageButton btnState;
/**
- 下一部按钮
*/
private ImageButton btnNext;
/**
- 调节音量按钮
*/
private ImageButton btnVolume;
private View controlView = null;
private PopupWindow popupControl;
/**
- 音量视图
*/
private VolumeView volumeView;
private PopupWindow popupVolume;
private View extralView;
private PopupWindow extralWindow = null;
private static int screenWidth = 0;
private static int screenHeight = 0;
private static int controlHeight = 0;
private final static int TIME = 6868;
private boolean isControllerShow = true;
private boolean isPaused = false;
private boolean isFullScreen = false;
private boolean isSilent = false;
private boolean isSoundShow = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialLayout();
Looper.myQueue().addIdleHandler(new IdleHandler() {
@Override
public boolean queueIdle() {
if (popupControl != null && videoView.isShown()) {
popupControl.showAtLocation(videoView, Gravity.BOTTOM, 0, 0);
// controler.update(screenWidth, controlHeight);
popupControl.update(0, 0, screenWidth, controlHeight);
}
if (extralWindow != null && videoView.isShown()) {
extralWindow.showAtLocation(videoView, Gravity.TOP, 0, 0);
extralWindow.update(0, 25, screenWidth, 60);
}
// myHandler.sendEmptyMessageDelayed(HIDE_CONTROLER, TIME);
return false;
}
});
controlView = getLayoutInflater().inflate(R.layout.controler, null);
popupControl = new PopupWindow(controlView);
textTimeTotal = (TextView) controlView.findViewById(R.id.textTimeTotal);
textTimePlay = (TextView) controlView.findViewById(R.id.textTimePlay);
volumeView = new VolumeView(this);
volumeView.setOnVolumeChangeListener(new VolumeView.OnVolumeChangedListener() {
@Override
public void setYourVolume(int index) {
cancelDelayHide();
updateVolume(index);
hideControllerDelay();
}
});
popupVolume = new PopupWindow(volumeView);
extralView = getLayoutInflater().inflate(R.layout.extral, null);
extralWindow = new PopupWindow(extralView);
ImageButton btnBack = (ImageButton) extralView
.findViewById(R.id.btnBack);
position = -1;
btnBack.setOnClickListener(myOnClickListener);
btnList = (ImageButton) controlView.findViewById(R.id.btnList);
btnPrevious = (ImageButton) controlView.findViewById(R.id.btnPrevious);
btnState = (ImageButton) controlView.findViewById(R.id.btnState);
btnNext = (ImageButton) controlView.findViewById(R.id.btnNext);
btnVolume = (ImageButton) controlView.findViewById(R.id.btnVolume);
videoView = (VideoView) findViewById(R.id.videoView);
videoView.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
videoView.stopPlayback();
isOnline = false;
new AlertDialog.Builder(VideoPlayerActivity.this)
.setTitle(“Error”)
.setMessage(“?”)
.setPositiveButton(“Confirm”,
new AlertDialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
videoView.stopPlayback();
}
}).setCancelable(false).show();
return false;
}
});
Uri uri = getIntent().getData();
if (uri != null) {
videoView.stopPlayback();
videoView.setVideoURI(uri);
isOnline = true;
btnState.setImageResource(R.drawable.pause);
} else {
btnState.setImageResource(R.drawable.play);
}
getVideoFile(playList, new File(“/sdcard/”));
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
Cursor cursor = getContentResolver()
.query(videoListUri,
new String[]{“_display_name”, “_data”}, null,
null, null);
int n = cursor.getCount();
cursor.moveToFirst();
LinkedList playList2 = new LinkedList();
for (int i = 0; i != n; ++i) {
VideoInfo videoInfo = new VideoInfo(cursor.getString(cursor
.getColumnIndex(“_display_name”)), cursor.getString(cursor.getColumnIndex(“_data”)));
playList2.add(videoInfo);
cursor.moveToNext();
}
if (playList2.size() > playList.size()) {
playList = playList2;
}
}
videoView.setMySizeChangeLinstener(new VideoView.MySizeChangeLinstener() {
@Override
public void doMyThings() {
setVideoScale(SCREEN_DEFAULT);
}
});
btnList.setAlpha(0xBB);
btnPrevious.setAlpha(0xBB);
btnState.setAlpha(0xBB);
btnNext.setAlpha(0xBB);
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
currentVolume = mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC);
btnVolume.setAlpha(getAlphaByVolume());
btnList.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setClass(VideoPlayerActivity.this,
VideoChooseActivity.class);
VideoPlayerActivity.this.startActivityForResult(intent, 0);
cancelDelayHide();
}
});
btnNext.setOnClickListener(myOnClickListener);
btnState.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
cancelDelayHide();
if (isPaused) {
videoView.start();
btnState.setImageResource(R.drawable.pause);
hideControllerDelay();
} else {
videoView.pause();
btnState.setImageResource(R.drawable.play);
}
isPaused = !isPaused;
}
});
btnPrevious.setOnClickListener(myOnClickListener);
btnVolume.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
cancelDelayHide();
if (isSoundShow) {
popupVolume.dismiss();
} else {
if (popupVolume.isShowing()) {
popupVolume.update(15, 0, VolumeView.MY_WIDTH,
VolumeView.MY_HEIGHT);
} else {
popupVolume.showAtLocation(videoView, Gravity.RIGHT
| Gravity.CENTER_VERTICAL, 15, 0);
popupVolume.update(15, 0, VolumeView.MY_WIDTH,
VolumeView.MY_HEIGHT);
}
}
isSoundShow = !isSoundShow;
hideControllerDelay();
}
});
btnVolume.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View arg0) {
if (isSilent) {
btnVolume.setImageResource(R.drawable.soundenable);
} else {
btnVolume.setImageResource(R.drawable.sounddisable);
}
isSilent = !isSilent;
updateVolume(currentVolume);
cancelDelayHide();
hideControllerDelay();
return true;
}
});
seekBar = (SeekBar) controlView.findViewById(R.id.seekbar);
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekbar, int progress,
boolean fromUser) {
if (fromUser) {
if (!isOnline) {
videoView.seekTo(progress);
}
}
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
myHandler.removeMessages(HIDE_CONTROLER);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
myHandler.sendEmptyMessageDelayed(HIDE_CONTROLER, TIME);
}
});
getScreenSize();
mGestureDetector = new GestureDetector(new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (isFullScreen) {
setVideoScale(SCREEN_DEFAULT);
} else {
setVideoScale(SCREEN_FULL);
}
isFullScreen = !isFullScreen;
Log.d(TAG, “onDoubleTap”);
if (isControllerShow) {
showController();
}
// return super.onDoubleTap(e);
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (!isControllerShow) {
showController();
hideControllerDelay();
} else {
cancelDelayHide();
hideController();
}
// return super.onSingleTapConfirmed(e);
return true;
}
@Override
public void onLongPress(MotionEvent e) {
if (isPaused) {
videoView.start();
最后
都说三年是程序员的一个坎,能否晋升或者提高自己的核心竞争力,这几年就十分关键。
技术发展的这么快,从哪些方面开始学习,才能达到高级工程师水平,最后进阶到Android架构师/技术专家?我总结了这 5大块;
我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 PDF(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言
高级UI与自定义view;
自定义view,Android开发的基本功。
性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。
NDK开发;
未来的方向,高薪必会。
前沿技术;
组件化,热升级,热修复,框架设计
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多
当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。
不出半年,你就能看出变化!
加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0
Handler.sendEmptyMessageDelayed(HIDE_CONTROLER, TIME);
}
});
getScreenSize();
mGestureDetector = new GestureDetector(new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (isFullScreen) {
setVideoScale(SCREEN_DEFAULT);
} else {
setVideoScale(SCREEN_FULL);
}
isFullScreen = !isFullScreen;
Log.d(TAG, “onDoubleTap”);
if (isControllerShow) {
showController();
}
// return super.onDoubleTap(e);
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (!isControllerShow) {
showController();
hideControllerDelay();
} else {
cancelDelayHide();
hideController();
}
// return super.onSingleTapConfirmed(e);
return true;
}
@Override
public void onLongPress(MotionEvent e) {
if (isPaused) {
videoView.start();
最后
都说三年是程序员的一个坎,能否晋升或者提高自己的核心竞争力,这几年就十分关键。
技术发展的这么快,从哪些方面开始学习,才能达到高级工程师水平,最后进阶到Android架构师/技术专家?我总结了这 5大块;
我搜集整理过这几年阿里,以及腾讯,字节跳动,华为,小米等公司的面试题,把面试的要求和技术点梳理成一份大而全的“ Android架构师”面试 PDF(实际上比预期多花了不少精力),包含知识脉络 + 分支细节。
[外链图片转存中…(img-BIY5m3ke-1725645968358)]
Java语言与原理;
大厂,小厂。Android面试先看你熟不熟悉Java语言
[外链图片转存中…(img-zJiPOVhw-1725645968358)]
高级UI与自定义view;
自定义view,Android开发的基本功。
[外链图片转存中…(img-d5RyYFJv-1725645968359)]
性能调优;
数据结构算法,设计模式。都是这里面的关键基础和重点需要熟练的。
[外链图片转存中…(img-EuNx8CT1-1725645968359)]
NDK开发;
未来的方向,高薪必会。
[外链图片转存中…(img-yUVOZJ8J-1725645968360)]
前沿技术;
组件化,热升级,热修复,框架设计
[外链图片转存中…(img-mjaKoCtI-1725645968360)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
我在搭建这些技术框架的时候,还整理了系统的高级进阶教程,会比自己碎片化学习效果强太多
当然,想要深入学习并掌握这些能力,并不简单。关于如何学习,做程序员这一行什么工作强度大家都懂,但是不管工作多忙,每周也要雷打不动的抽出 2 小时用来学习。
不出半年,你就能看出变化!
加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0