├── .gitignore ├── BlueVideoPlayer.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── libs │ └── android-image-cache-master.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── com │ │ └── bluevideoplayer │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── com │ │ └── bluevideoplayer │ │ ├── MainActivity.java │ │ ├── MainApplication.java │ │ ├── NetPlayActivity.java │ │ ├── PlayActivity.java │ │ ├── SettingActivity.java │ │ ├── fragments │ │ ├── FileInfoAdapter.java │ │ ├── FolderFragment.java │ │ ├── FolderLoader.java │ │ ├── LoaderCursor.java │ │ ├── LoaderFiles.java │ │ └── SettingFragment.java │ │ └── util │ │ ├── DarkButton.java │ │ ├── LoadingDialog.java │ │ ├── Logger.java │ │ ├── MarqueeText.java │ │ ├── SpManager.java │ │ ├── ToastManager.java │ │ └── Util.java │ └── res │ ├── anim │ ├── slide_bottom_out.xml │ ├── slide_buttom_in.xml │ ├── slide_left_in.xml │ ├── slide_left_out.xml │ ├── slide_right_in.xml │ ├── slide_right_out.xml │ ├── slide_top_in.xml │ └── slide_top_out.xml │ ├── drawable │ ├── arrow_cue.png │ ├── bg_music_playbg1.png │ ├── bg_music_playbg3.9.png │ ├── blue_down.9.png │ ├── blue_normal.9.png │ ├── button_blue_click.xml │ ├── button_last_play_click.xml │ ├── button_refresh_click.xml │ ├── divider.png │ ├── dr_btn_press.9.png │ ├── fast_back.jpg │ ├── fast_forward.jpg │ ├── file.png │ ├── folder.png │ ├── foler_background.png │ ├── go_bbs_btn_normal.9.png │ ├── icon_movie_normal.png │ ├── icon_play_down.png │ ├── icon_play_normal.png │ ├── icon_refresh_down.png │ ├── icon_refresh_normal.png │ ├── icon_setting.png │ ├── image_progress.xml │ ├── last.jpg │ ├── launcher.png │ ├── lock_1.png │ ├── lock_3.png │ ├── media_player_progress_button.png │ ├── next.png │ ├── pause.png │ ├── play.jpg │ ├── progress_bar_circle.png │ ├── progress_bar_layer.xml │ ├── stop.jpg │ ├── video_brightness_bg.png │ ├── video_num_bg.png │ ├── video_num_front.png │ └── video_volume_bg.png │ ├── layout │ ├── activity_main.xml │ ├── file_info.xml │ ├── file_info_item.xml │ ├── mediaplayer_2.xml │ ├── myalert.xml │ ├── play.xml │ ├── tab_list.xml │ └── video_item.xml │ ├── menu │ ├── main.xml │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ ├── values │ ├── arrays.xml │ ├── color.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── preferences.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── vitamio ├── .classpath ├── .project ├── AndroidManifest.xml ├── README.md ├── build.gradle ├── libs ├── armeabi-v7a │ └── libvinit.so ├── armeabi │ └── libvinit.so └── x86 │ └── libvinit.so ├── lint.xml ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ ├── ic_launcher.png │ ├── mediacontroller_bg.png │ ├── mediacontroller_pause01.png │ ├── mediacontroller_pause02.png │ ├── mediacontroller_play01.png │ └── mediacontroller_play02.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ ├── ic_launcher.png │ ├── scrubber_control_disabled_holo.png │ ├── scrubber_control_focused_holo.png │ ├── scrubber_control_normal_holo.png │ ├── scrubber_control_pressed_holo.png │ ├── scrubber_primary_holo.9.png │ ├── scrubber_secondary_holo.9.png │ └── scrubber_track_holo_dark.9.png ├── drawable │ ├── mediacontroller_pause_button.xml │ ├── mediacontroller_play_button.xml │ ├── scrubber_control_selector_holo.xml │ └── scrubber_progress_horizontal_holo_dark.xml ├── layout │ └── mediacontroller.xml ├── raw │ └── libarm.so └── values │ ├── strings.xml │ └── styles.xml ├── src └── io │ └── vov │ └── vitamio │ ├── EGL.java │ ├── LibsChecker.java │ ├── MediaFile.java │ ├── MediaMetadataRetriever.java │ ├── MediaPlayer.java │ ├── MediaScanner.java │ ├── MediaScannerClient.java │ ├── Metadata.java │ ├── ThumbnailUtils.java │ ├── VIntent.java │ ├── Vitamio.java │ ├── VitamioLicense.java │ ├── activity │ └── InitActivity.java │ ├── provider │ ├── MediaStore.java │ └── MiniThumbFile.java │ ├── utils │ ├── Base64.java │ ├── CPU.java │ ├── ContextUtils.java │ ├── Crypto.java │ ├── Device.java │ ├── FileUtils.java │ ├── IOUtils.java │ ├── Log.java │ └── StringUtils.java │ └── widget │ ├── CenterLayout.java │ ├── MediaController.java │ ├── OutlineTextView.java │ └── VideoView.java └── vitamio.iml /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea/ 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | # Built application files 9 | *.apk 10 | *.ap_ 11 | 12 | # Files for the Dalvik VM 13 | *.dex 14 | 15 | # Java class files 16 | *.class 17 | 18 | # Generated files 19 | bin/ 20 | gen/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | /*/build/ 26 | 27 | # Local configuration file (sdk path, etc) 28 | local.properties 29 | 30 | # Proguard folder generated by Eclipse 31 | proguard/ 32 | 33 | # Log Files 34 | *.log -------------------------------------------------------------------------------- /BlueVideoPlayer.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "cn.com.bluevideoplayer" 9 | minSdkVersion 21 10 | targetSdkVersion 21 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | compile 'com.android.support:appcompat-v7:21.0.3' 25 | compile project(':vitamio') 26 | } 27 | -------------------------------------------------------------------------------- /app/libs/android-image-cache-master.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/libs/android-image-cache-master.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\work software\sdk\android_sdk_windows\android_sdk_windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/com/bluevideoplayer/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 32 | 33 | 34 | 38 | 39 | 40 | 41 | 44 | 47 | 48 | 49 | 50 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/MainApplication.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer; 2 | 3 | 4 | import android.app.Application; 5 | import android.content.ContextWrapper; 6 | 7 | import edu.mit.mobile.android.imagecache.ImageCache; 8 | 9 | /** 10 | * app运行的Application 11 | * 12 | * @author Administrator 13 | */ 14 | public class MainApplication extends Application { 15 | public static ContextWrapper mContext; 16 | public static ImageCache mCache; 17 | 18 | @Override 19 | public void onCreate() { 20 | super.onCreate(); 21 | mContext = this; 22 | mCache = ImageCache.getInstance(mContext); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer; 2 | 3 | import android.app.ActionBar; 4 | import android.os.Bundle; 5 | import android.preference.Preference; 6 | import android.preference.Preference.OnPreferenceClickListener; 7 | import android.preference.PreferenceActivity; 8 | import android.view.MenuItem; 9 | 10 | import cn.com.bluevideoplayer.util.SpManager; 11 | import cn.com.bluevideoplayer.util.ToastManager; 12 | 13 | public class SettingActivity extends PreferenceActivity { 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | ActionBar bar = getActionBar(); 18 | bar.setBackgroundDrawable(getResources() 19 | .getDrawable(R.drawable.divider)); 20 | 21 | bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME 22 | | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_USE_LOGO); 23 | bar.setTitle(R.string.setting); 24 | bar.setDisplayShowHomeEnabled(true); 25 | bar.setDisplayHomeAsUpEnabled(true); 26 | // Load the preferences from an XML resource 27 | addPreferencesFromResource(R.xml.preferences); 28 | 29 | Preference preference0 = findPreference("clear"); 30 | 31 | preference0 32 | .setOnPreferenceClickListener(new OnPreferenceClickListener() { 33 | 34 | @Override 35 | public boolean onPreferenceClick(Preference preference) { 36 | SpManager.clear(SettingActivity.this); 37 | ToastManager.show(SettingActivity.this, R.string.cleared); 38 | return false; 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public void onBackPressed() { 45 | super.onBackPressed(); 46 | overridePendingTransition(R.anim.slide_right_in, R.anim.slide_right_out); 47 | } 48 | 49 | @Override 50 | public boolean onOptionsItemSelected(MenuItem item) { 51 | if (item.getItemId() == android.R.id.home) { 52 | onBackPressed(); 53 | return true; 54 | } 55 | return super.onOptionsItemSelected(item); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/fragments/FileInfoAdapter.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.fragments; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.provider.MediaStore; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.BaseAdapter; 10 | import android.widget.TextView; 11 | 12 | import cn.com.bluevideoplayer.R; 13 | import cn.com.bluevideoplayer.util.Util; 14 | 15 | public class FileInfoAdapter extends BaseAdapter { 16 | private static LayoutInflater mInflater; 17 | private Context mContext; 18 | private String[] INFOS; 19 | private String[] COLUMNS = new String[7]; 20 | private Cursor mCursor; 21 | 22 | public FileInfoAdapter(Context context, Cursor c) { 23 | mCursor = c; 24 | mContext = context; 25 | 26 | INFOS = mContext.getResources().getStringArray( 27 | R.array.file_info_array); 28 | mInflater = (LayoutInflater) mContext 29 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 30 | COLUMNS[0] = mCursor.getString(mCursor 31 | .getColumnIndex(MediaStore.Video.Media.TITLE)); 32 | COLUMNS[1] = Util.getReadableFileSize(mCursor.getLong(mCursor 33 | .getColumnIndex(MediaStore.Video.Media.SIZE))); 34 | COLUMNS[2] = Util.getDuration(mCursor.getLong(mCursor 35 | .getColumnIndex(MediaStore.Video.Media.DURATION))); 36 | COLUMNS[3] = Util.getDateTime(mCursor.getLong(mCursor 37 | .getColumnIndex(MediaStore.Video.Media.DATE_TAKEN))); 38 | COLUMNS[4] = mCursor.getString(mCursor 39 | .getColumnIndex(MediaStore.Video.Media.DATA)); 40 | COLUMNS[5] = mCursor.getString(mCursor 41 | .getColumnIndex(MediaStore.Video.Media.RESOLUTION)); 42 | COLUMNS[6] = mCursor.getString(mCursor 43 | .getColumnIndex(MediaStore.Video.Media.MIME_TYPE)); 44 | } 45 | 46 | @Override 47 | public int getCount() { 48 | return INFOS.length; 49 | } 50 | 51 | @Override 52 | public Object getItem(int position) { 53 | return INFOS[position]; 54 | } 55 | 56 | @Override 57 | public long getItemId(int position) { 58 | return position; 59 | } 60 | 61 | @Override 62 | public View getView(int position, View convertView, ViewGroup parent) { 63 | convertView = mInflater.inflate(R.layout.file_info_item, null); 64 | TextView key = (TextView) convertView.findViewById(R.id.key); 65 | TextView value = (TextView) convertView.findViewById(R.id.value); 66 | key.setText(INFOS[position]); 67 | value.setText(COLUMNS[position]); 68 | // if (position == 0) { 69 | // convertView.setBackgroundResource(R.drawable.list_top); 70 | // } else if (position == getCount() - 1) { 71 | // convertView.setBackgroundResource(R.drawable.list_bottom); 72 | // }else{ 73 | // convertView.setBackgroundResource(R.drawable.list_middle); 74 | // } 75 | return convertView; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/fragments/FolderLoader.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.fragments; 2 | 3 | import android.content.AsyncTaskLoader; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.provider.MediaStore; 7 | 8 | import java.io.File; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.Iterator; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Map.Entry; 15 | import java.util.Set; 16 | 17 | import cn.com.bluevideoplayer.fragments.FolderFragment.Folders; 18 | import cn.com.bluevideoplayer.util.Logger; 19 | 20 | public class FolderLoader extends AsyncTaskLoader> { 21 | private static final String TAG = "FolderLoader"; 22 | Context mContext; 23 | List mList = new ArrayList(); 24 | List mAddedList = new ArrayList(); 25 | Map map = new HashMap(); 26 | 27 | public FolderLoader(Context context) { 28 | super(context); 29 | mContext = context; 30 | Logger.d(TAG, "FolderLoader"); 31 | } 32 | 33 | @Override 34 | public List loadInBackground() { 35 | Logger.d(TAG, "loadInBackground"); 36 | map.clear(); 37 | mList.clear(); 38 | Cursor c = mContext.getContentResolver().query( 39 | MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 40 | FolderFragment.FOLDER_PROJECTIONS, null, null, null); 41 | int column = c.getColumnIndex(MediaStore.Video.Media.DATA); 42 | while (c.moveToNext()) { 43 | String path = c.getString(column); 44 | path = path.substring(0, path.lastIndexOf(File.separator)); 45 | if (map.containsKey(path)) { 46 | int count = map.get(path); 47 | map.put(path, count + 1); 48 | } else { 49 | map.put(path, 1); 50 | } 51 | } 52 | c.close(); 53 | Set> set = map.entrySet(); 54 | Iterator> i = set.iterator(); 55 | while (i.hasNext()) { 56 | Entry entry = i.next(); 57 | Folders folders = new Folders(); 58 | folders.path = entry.getKey(); 59 | folders.children = entry.getValue(); 60 | mList.add(folders); 61 | } 62 | return mList; 63 | } 64 | 65 | @Override 66 | protected void onStartLoading() { 67 | Logger.d(TAG, "onStartLoading"); 68 | if (mList.size() > 0) { 69 | deliverResult(mList); 70 | } else { 71 | forceLoad(); 72 | } 73 | } 74 | 75 | @Override 76 | public void deliverResult(List files) { 77 | Logger.d(TAG, "deliverResult"); 78 | super.deliverResult(files); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/fragments/SettingFragment.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.fragments; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.preference.Preference; 6 | import android.preference.Preference.OnPreferenceClickListener; 7 | import android.preference.PreferenceFragment; 8 | 9 | import cn.com.bluevideoplayer.R; 10 | import cn.com.bluevideoplayer.util.SpManager; 11 | import cn.com.bluevideoplayer.util.ToastManager; 12 | 13 | public class SettingFragment extends PreferenceFragment { 14 | Context mContext; 15 | 16 | @Override 17 | public void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | mContext = this.getActivity(); 20 | // Load the preferences from an XML resource 21 | addPreferencesFromResource(R.xml.preferences); 22 | 23 | Preference preference0 = findPreference("clear"); 24 | 25 | preference0 26 | .setOnPreferenceClickListener(new OnPreferenceClickListener() { 27 | 28 | @Override 29 | public boolean onPreferenceClick(Preference preference) { 30 | SpManager.clear(mContext); 31 | ToastManager.show(mContext, "清除完成"); 32 | return false; 33 | } 34 | }); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/DarkButton.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.LightingColorFilter; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | import android.widget.Button; 8 | 9 | public class DarkButton extends Button { 10 | 11 | public DarkButton(Context context) { 12 | super(context); 13 | } 14 | 15 | public DarkButton(Context context, AttributeSet attrs) { 16 | super(context, attrs); 17 | } 18 | 19 | 20 | @Override 21 | public boolean onTouchEvent(MotionEvent event) { 22 | switch (event.getAction()) { 23 | case MotionEvent.ACTION_DOWN: 24 | // darken background 25 | getBackground().setColorFilter( 26 | new LightingColorFilter(0xff888888, 0x000000)); 27 | break; 28 | 29 | case MotionEvent.ACTION_UP: 30 | // clear color filter 31 | getBackground().setColorFilter(null); 32 | break; 33 | } 34 | return super.onTouchEvent(event); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/LoadingDialog.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.widget.ProgressBar; 7 | 8 | import cn.com.bluevideoplayer.R; 9 | 10 | public class LoadingDialog extends ProgressDialog { 11 | // 要指定样式,调用此构造方法 12 | public LoadingDialog(Context context, int theme) { 13 | super(context, theme); 14 | } 15 | 16 | // 默认使用R.style.my_dialog_style 17 | public LoadingDialog(Context context) { 18 | super(context, R.style.my_dialog_style); 19 | } 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | //setScreenBrightness(); 25 | setContentView(R.layout.myalert); 26 | 27 | ProgressBar image = (ProgressBar) LoadingDialog.this 28 | .findViewById(R.id.loading_img); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/Logger.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * 封装打印类,主要是为了更好的控制打印 7 | * 8 | * @author liyanshun 9 | */ 10 | public class Logger { 11 | /** 12 | * 打印log的开关 13 | */ 14 | private static final boolean IS_DEBUG = Util.DEBUG; 15 | // 内部断定是否显示log信息 16 | private static boolean mIsInnerShowLog = IS_DEBUG; 17 | 18 | /** 19 | * 得到被打印的文件名行数等信息 20 | */ 21 | private static String getFunctionName() { 22 | StackTraceElement[] sts = Thread.currentThread().getStackTrace(); 23 | if (sts == null) { 24 | return null; 25 | } 26 | for (StackTraceElement st : sts) { 27 | if (st.isNativeMethod()) { 28 | continue; 29 | } 30 | if (st.getClassName().equals(Thread.class.getName())) { 31 | continue; 32 | } 33 | if (st.getClassName().equals( 34 | "cn.com.bluevideoplayer.util.Logger")) { 35 | continue; 36 | } 37 | return "[Line: " + st.getLineNumber() + "]"; 38 | } 39 | return null; 40 | } 41 | 42 | public static void i(String tag, Object message) { 43 | if (mIsInnerShowLog) { 44 | String name = getFunctionName(); 45 | if (name == null) { 46 | Log.i(tag, " [OutPut :" + message.toString() + "]"); 47 | } else { 48 | Log.i(tag, name + " [OutPut :" + message.toString() + "]"); 49 | } 50 | 51 | } 52 | } 53 | 54 | public static void d(String tag, Object message) { 55 | if (mIsInnerShowLog) { 56 | String name = getFunctionName(); 57 | if (name == null) { 58 | Log.d(tag, " [OutPut :" + message.toString() + "]"); 59 | } else { 60 | Log.d(tag, name + " [OutPut :" + message.toString() + "]"); 61 | } 62 | } 63 | } 64 | 65 | public static void v(String tag, Object message) { 66 | if (mIsInnerShowLog) { 67 | String name = getFunctionName(); 68 | if (name == null) { 69 | Log.v(tag, " [OutPut :" + message.toString() + "]"); 70 | } else { 71 | Log.v(tag, name + " [OutPut :" + message.toString() + "]"); 72 | } 73 | } 74 | } 75 | 76 | public static void w(String tag, Object message) { 77 | if (mIsInnerShowLog) { 78 | String name = getFunctionName(); 79 | if (name == null) { 80 | Log.w(tag, " [OutPut :" + message.toString() + "]"); 81 | } else { 82 | Log.w(tag, name + " [OutPut :" + message.toString() + "]"); 83 | } 84 | } 85 | } 86 | 87 | public static void e(String tag, Object message) { 88 | if (mIsInnerShowLog) { 89 | String name = getFunctionName(); 90 | if (name == null) { 91 | Log.e(tag, " [OutPut :" + message + "]"); 92 | } else { 93 | Log.e(tag, name + " [OutPut :" + message + "]"); 94 | } 95 | 96 | } 97 | } 98 | 99 | public static void e(String tag, Exception e) { 100 | if (mIsInnerShowLog) { 101 | String name = getFunctionName(); 102 | if (name == null) { 103 | Log.e(tag, " [OutPut :" + e.getMessage() + "]"); 104 | } else { 105 | Log.e(tag, name + " [OutPut :" + e.getMessage() + "]"); 106 | } 107 | 108 | } 109 | } 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/MarqueeText.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.util.AttributeSet; 6 | import android.widget.TextView; 7 | 8 | public class MarqueeText extends TextView { 9 | 10 | public MarqueeText(Context context) { 11 | super(context); 12 | // TODO Auto-generated constructor stub 13 | } 14 | 15 | public MarqueeText(Context context, AttributeSet attrs) { 16 | super(context, attrs); 17 | } 18 | 19 | public MarqueeText(Context context, AttributeSet attrs, int defStyle) { 20 | super(context, attrs, defStyle); 21 | } 22 | 23 | @Override 24 | protected void onFocusChanged(boolean focused, int direction, 25 | Rect previouslyFocusedRect) { 26 | if (focused) 27 | super.onFocusChanged(focused, direction, previouslyFocusedRect); 28 | } 29 | 30 | @Override 31 | public void onWindowFocusChanged(boolean focused) { 32 | if (focused) 33 | super.onWindowFocusChanged(focused); 34 | } 35 | 36 | @Override 37 | public boolean isFocused() { 38 | return true; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/SpManager.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.content.SharedPreferences.Editor; 6 | import android.text.TextUtils; 7 | 8 | import java.util.HashMap; 9 | import java.util.Iterator; 10 | 11 | public class SpManager { 12 | 13 | private static HashMap BREAK_POINT_MAP = new HashMap(); 14 | private static String LAST_PLAY; 15 | 16 | public static void clear(Context c) { 17 | BREAK_POINT_MAP.clear(); 18 | LAST_PLAY = null; 19 | SharedPreferences spf = c.getSharedPreferences("last_play", 0); 20 | Editor editor = spf.edit(); 21 | editor.clear(); 22 | editor.commit(); 23 | 24 | spf = c.getSharedPreferences("break_point", 0); 25 | editor = spf.edit(); 26 | editor.clear(); 27 | editor.commit(); 28 | } 29 | 30 | public static void remove(Context c, String path) { 31 | if (path.equals(LAST_PLAY)) { 32 | LAST_PLAY = null; 33 | } 34 | BREAK_POINT_MAP.remove(path); 35 | SharedPreferences spf = c.getSharedPreferences("last_play", 0); 36 | Editor editor = spf.edit(); 37 | editor.remove(path); 38 | editor.clear(); 39 | 40 | spf = c.getSharedPreferences("break_point", 0); 41 | editor = spf.edit(); 42 | editor.remove(path); 43 | editor.clear(); 44 | } 45 | 46 | public static void saveLastPlay(Context c, String path) { 47 | SharedPreferences spf = c.getSharedPreferences("last_play", 0); 48 | Editor editor = spf.edit(); 49 | editor.putString("last_play", path); 50 | editor.commit(); 51 | } 52 | 53 | /** 54 | * 获得最后播放视频的地址 55 | * 56 | * @param c 57 | * @return 58 | */ 59 | public static String getLastPlay(Context c) { 60 | if (TextUtils.isEmpty(LAST_PLAY)) { 61 | SharedPreferences spf = c.getSharedPreferences("last_play", 0); 62 | return spf.getString("last_play", null); 63 | } else { 64 | return LAST_PLAY; 65 | } 66 | } 67 | 68 | /** 69 | * 将所有的断点信息保存起来 70 | * 71 | * @param c 72 | */ 73 | public static void saveAllBreakPoint(Context c) { 74 | SharedPreferences spf = c.getSharedPreferences("break_point", 0); 75 | Editor editor = spf.edit(); 76 | // editor.clear(); 77 | Iterator keys = BREAK_POINT_MAP.keySet().iterator(); 78 | while (keys.hasNext()) { 79 | String key = (String) keys.next(); 80 | int value = BREAK_POINT_MAP.get(key); 81 | editor.putInt(key, value); 82 | } 83 | editor.commit(); 84 | saveLastPlay(c, LAST_PLAY); 85 | } 86 | 87 | /** 88 | * 获得指定视频的断点 89 | * 90 | * @param c 91 | * @param path 92 | * @return 93 | */ 94 | public static int getBreakPoint(Context c, String path) { 95 | if (BREAK_POINT_MAP.containsKey(path)) { 96 | return BREAK_POINT_MAP.get(path); 97 | } else { 98 | SharedPreferences spf = c.getSharedPreferences("break_point", 0); 99 | int breakPoint = spf.getInt(path, 0); 100 | BREAK_POINT_MAP.put(path, breakPoint); 101 | return breakPoint; 102 | } 103 | } 104 | 105 | /** 106 | * 设置key的断点信息 107 | * 108 | * @param key 109 | * @param value 110 | */ 111 | public static void setBreakPoint(String key, int value) { 112 | BREAK_POINT_MAP.put(key, value); 113 | LAST_PLAY = key; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/ToastManager.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.view.Gravity; 7 | import android.widget.Toast; 8 | 9 | /** 10 | * Toast管理类 11 | * 12 | * @author wenhaoran 13 | * @version 4.0 14 | * @time 2013/4/15 15 | */ 16 | public class ToastManager { 17 | 18 | private static final int SHOW_STRING = 0; 19 | private static final int SHOW_INT = 1; 20 | private static Context mContext; 21 | private static Handler mHandler = new Handler() { 22 | 23 | @Override 24 | public void handleMessage(Message msg) { 25 | switch (msg.what) { 26 | case SHOW_STRING: 27 | show(mContext, (String) msg.obj, false); 28 | break; 29 | case SHOW_INT: 30 | show(mContext, mContext.getString(msg.arg1), false); 31 | break; 32 | } 33 | super.handleMessage(msg); 34 | } 35 | 36 | }; 37 | 38 | /** 39 | * 显示String类型的Toast 40 | * 41 | * @param context 42 | * @param msg 43 | */ 44 | public static void show(Context context, String msg) { 45 | mContext = context; 46 | Message message = new Message(); 47 | message.what = SHOW_STRING; 48 | message.obj = msg; 49 | mHandler.sendMessage(message); 50 | } 51 | 52 | /** 53 | * 显示int类型的Toast 54 | * 55 | * @param context 56 | * @param id 57 | */ 58 | public static void show(Context context, int id) { 59 | mContext = context; 60 | Message message = new Message(); 61 | message.what = SHOW_INT; 62 | message.arg1 = id; 63 | mHandler.sendMessage(message); 64 | } 65 | 66 | /** 67 | * 显示toast 68 | * 69 | * @param context 70 | * @param msg 71 | * @param isLong 时间控制,true为LENGTH_LONG,false为LENGTH_SHORT 72 | */ 73 | public static void show(Context context, String msg, boolean isLong) { 74 | mContext = context; 75 | if (null != msg && !"".equalsIgnoreCase(msg)) { 76 | if (isLong) { 77 | Toast toast = Toast.makeText(context, msg, Toast.LENGTH_LONG); 78 | toast.setGravity(Gravity.BOTTOM, 0, 0); 79 | toast.show(); 80 | } else { 81 | Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); 82 | toast.setGravity(Gravity.BOTTOM, 0, 0); 83 | 84 | toast.show(); 85 | } 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/cn/com/bluevideoplayer/util/Util.java: -------------------------------------------------------------------------------- 1 | package cn.com.bluevideoplayer.util; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.provider.MediaStore; 6 | import android.webkit.MimeTypeMap; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import java.io.File; 11 | import java.text.DecimalFormat; 12 | import java.text.SimpleDateFormat; 13 | import java.util.ArrayList; 14 | import java.util.Date; 15 | 16 | import cn.com.bluevideoplayer.R; 17 | 18 | public class Util { 19 | public static final String CURSOR = "CURSOR"; 20 | public static final boolean DEBUG = true; 21 | public static final String[] PROJECTIONS = {MediaStore.Video.Media.TITLE, 22 | MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DURATION, 23 | MediaStore.Video.Media.DATE_TAKEN, 24 | MediaStore.Video.Media.DATE_ADDED, 25 | MediaStore.Video.Media.RESOLUTION, 26 | MediaStore.Video.Media.MIME_TYPE, MediaStore.Video.Media.DATA, 27 | MediaStore.Video.Media._ID,}; 28 | static final int BYTES_IN_KILOBYTES = 1024; 29 | static final DecimalFormat dec = new DecimalFormat("###.#"); 30 | static final String KILOBYTES = " KB"; 31 | static final String MEGABYTES = " MB"; 32 | static final String GIGABYTES = " GB"; 33 | static final SimpleDateFormat FORMAT = new SimpleDateFormat( 34 | "yyyy-MM-dd HH:mm:ss"); 35 | static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); 36 | private static final String TAG = "Util"; 37 | 38 | /** 39 | * Gets the extension of a file name, like ".png" or ".jpg". 40 | * 41 | * @param uri 42 | * @return Extension including the dot("."); "" if there is no extension; 43 | * null if uri was null. 44 | */ 45 | public static String getExtension(String uri) { 46 | if (uri == null) { 47 | return null; 48 | } 49 | 50 | int dot = uri.lastIndexOf("."); 51 | if (dot >= 0) { 52 | return uri.substring(dot); 53 | } else { 54 | // No extension. 55 | return ""; 56 | } 57 | } 58 | 59 | /** 60 | * @return The MIME type for the given file. 61 | */ 62 | public static String getMimeType(File file) { 63 | 64 | String extension = getExtension(file.getName()); 65 | 66 | if (extension.length() > 0) 67 | return MimeTypeMap.getSingleton().getMimeTypeFromExtension( 68 | extension.substring(1)); 69 | 70 | return "application/octet-stream"; 71 | } 72 | 73 | /** 74 | * Get the file size in a human-readable string. 75 | * 76 | * @param size 77 | * @return 78 | * @author paulburke 79 | */ 80 | public static String getReadableFileSize(long size) { 81 | float fileSize = 0; 82 | String suffix = KILOBYTES; 83 | 84 | if (size > BYTES_IN_KILOBYTES) { 85 | fileSize = size / BYTES_IN_KILOBYTES; 86 | if (fileSize > BYTES_IN_KILOBYTES) { 87 | fileSize = fileSize / BYTES_IN_KILOBYTES; 88 | if (fileSize > BYTES_IN_KILOBYTES) { 89 | fileSize = fileSize / BYTES_IN_KILOBYTES; 90 | suffix = GIGABYTES; 91 | } else { 92 | suffix = MEGABYTES; 93 | } 94 | } 95 | } 96 | return String.valueOf(dec.format(fileSize) + suffix); 97 | } 98 | 99 | public static String getCurrentTime(long millSeconds) { 100 | Date date = new Date(millSeconds); 101 | return TIME_FORMAT.format(date); 102 | } 103 | 104 | public static String getDateTime(long millSeconds) { 105 | Date date = new Date(millSeconds); 106 | return FORMAT.format(date); 107 | } 108 | 109 | /** 110 | * 转化时长的格式到时:分:秒的格式 111 | * 112 | * @param time - 时间,以微妙的格式 113 | * @return 114 | */ 115 | public static String getDuration(long time) { 116 | time /= 1000; 117 | long minute = time / 60; 118 | long hour = minute / 60; 119 | long second = time % 60; 120 | minute %= 60; 121 | if (hour == 0) { 122 | return String.format("%02d:%02d", minute, second); 123 | } else { 124 | return String.format("%02d:%02d:%02d", hour, minute, second); 125 | } 126 | } 127 | 128 | public static ArrayList getChildFiles(String path) { 129 | ArrayList list = new ArrayList(); 130 | File f = new File(path); 131 | File[] child = null; 132 | if (f.isDirectory()) { 133 | child = f.listFiles(); 134 | } 135 | if (child != null) { 136 | for (File file : child) { 137 | list.add(file); 138 | } 139 | } 140 | return list; 141 | } 142 | 143 | public static CharSequence getTitle(String path) { 144 | int dot = path.lastIndexOf("."); 145 | int split = path.lastIndexOf(File.separator); 146 | if (dot >= 0 && split >= 0) { 147 | return path.substring(split + 1, dot); 148 | } else { 149 | return ""; 150 | } 151 | } 152 | 153 | public static CharSequence getFolderTitle(String path) { 154 | int split = path.lastIndexOf(File.separator); 155 | if (split >= 0) { 156 | return path.substring(split + 1, path.length()); 157 | } else { 158 | return ""; 159 | } 160 | } 161 | 162 | public static boolean deleteFile(Context c, File f) { 163 | if (f.delete()) { 164 | Logger.d(TAG, "delete succed"); 165 | ContentResolver resolver = c.getContentResolver(); 166 | resolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 167 | MediaStore.Video.Media.DATA + "=?", 168 | new String[]{f.getAbsolutePath()}); 169 | SpManager.remove(c, f.getAbsolutePath()); 170 | return true; 171 | } else { 172 | ToastManager.show(c, R.string.delete_fail); 173 | return false; 174 | } 175 | } 176 | 177 | public static final class ViewHolder { 178 | public TextView titleView; 179 | public TextView durationView; 180 | public TextView sizeView; 181 | public ImageView imgView; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_buttom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_top_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_top_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_cue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/arrow_cue.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_music_playbg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/bg_music_playbg1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_music_playbg3.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/bg_music_playbg3.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_down.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/blue_down.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/blue_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/blue_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_blue_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_last_play_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_refresh_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/divider.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/dr_btn_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/dr_btn_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/fast_back.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/fast_forward.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/fast_forward.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/file.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/folder.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/foler_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/foler_background.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/go_bbs_btn_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/go_bbs_btn_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_movie_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_movie_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_play_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_play_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_play_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_play_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_refresh_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_refresh_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_refresh_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_refresh_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/icon_setting.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/image_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/last.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/last.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/lock_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/lock_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/lock_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/media_player_progress_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/media_player_progress_button.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/next.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/pause.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/play.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/play.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress_bar_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/progress_bar_circle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress_bar_layer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 16 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/stop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/stop.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/video_brightness_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/video_brightness_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/video_num_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/video_num_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/video_num_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/video_num_front.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/video_volume_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/drawable/video_volume_bg.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/file_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/file_info_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/mediaplayer_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/myalert.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/play.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 22 | 23 | 32 | 33 | 39 | 40 | 45 | 46 | 52 | 53 | 60 | 61 | 62 | 63 | 67 | 68 | 74 | 75 | 90 | 91 | 104 | 105 | 106 | 111 | 112 | 121 | 122 | 127 | 128 | 135 | 136 | 143 | 144 | 151 | 152 | 159 | 160 | 167 | 168 | 169 | 170 | 176 | 177 | 188 | 189 | 200 | 201 | 212 | 213 | 214 | 215 | 216 | 225 | 226 | -------------------------------------------------------------------------------- /app/src/main/res/layout/tab_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/video_item.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | 16 | 21 | 22 | 34 | 35 | 40 | 41 | 50 | 51 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 11 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 视频名称 6 | 视频大小 7 | 视频时长 8 | 视频拍摄日期 9 | 视频添加日期 10 | 11 | 12 | 文件名: 13 | 文件大小: 14 | 时长: 15 | 拍摄日期: 16 | 路径: 17 | 分辨率: 18 | 格式: 19 | 20 | 21 | 0 22 | 1 23 | 2 24 | 3 25 | 4 26 | 27 | 28 | 升序 29 | 降序 30 | 31 | 32 | 0 33 | 1 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #50444449 4 | #666666 5 | #a9a9a9 6 | #22A5DF 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BluePlayer 5 | Settings 6 | 视频列表 7 | 文件夹列表 8 | 扫描开始 9 | 扫描结束 10 | 删除 11 | 详细信息 12 | 设置 13 | 清除完成 14 | 没有播放过的视频 15 | 无法播放该视频 16 | 选项 17 | 删除文件 18 | 你确定删除%1$s 19 | 你确定删除该文件夹里的所有的%1$s部视频吗? 20 | %1$s部视频 21 | 文件信息 22 | 删除失败 23 | %1$s/%2$s 24 | 关于 25 | 作者:qqliys 26 | 有任何意见或建议请联系qqliys@126.com,谢谢 27 | 28 | 视频排序 29 | 请选择排序依据的属性 30 | 排序类型 31 | 请选择排序的升降序 32 | 升序/降序 33 | 锁定屏幕 34 | 播放时锁定屏幕 35 | 选择后在播放时会锁定屏幕 36 | 清除播放记录 37 | 38 | 点击清除播放记录 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 18 | 19 | 23 | 24 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 25 | 26 | 27 | 30 | 31 | 32 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.5.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':vitamio' 2 | -------------------------------------------------------------------------------- /vitamio/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /vitamio/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | VitamioInitActivity 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /vitamio/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /vitamio/README.md: -------------------------------------------------------------------------------- 1 | Vitamio 2 | =============== 3 | 4 | This folder contains the main library which should be linked against as an 5 | Android library project in your application. 6 | -------------------------------------------------------------------------------- /vitamio/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | dependencies { 4 | } 5 | 6 | android { 7 | compileSdkVersion 21 8 | buildToolsVersion "21.1.2" 9 | defaultConfig { 10 | minSdkVersion 9 11 | targetSdkVersion 21 12 | } 13 | sourceSets { 14 | main { 15 | manifest.srcFile 'AndroidManifest.xml' 16 | java.srcDirs = ['src'] 17 | resources.srcDirs = ['src'] 18 | aidl.srcDirs = ['src'] 19 | renderscript.srcDirs = ['src'] 20 | res.srcDirs = ['res'] 21 | assets.srcDirs = ['assets'] 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vitamio/libs/armeabi-v7a/libvinit.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/libs/armeabi-v7a/libvinit.so -------------------------------------------------------------------------------- /vitamio/libs/armeabi/libvinit.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/libs/armeabi/libvinit.so -------------------------------------------------------------------------------- /vitamio/libs/x86/libvinit.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/libs/x86/libvinit.so -------------------------------------------------------------------------------- /vitamio/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /vitamio/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /vitamio/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-18 15 | android.library=true 16 | -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/mediacontroller_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/mediacontroller_bg.png -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/mediacontroller_pause01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/mediacontroller_pause01.png -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/mediacontroller_pause02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/mediacontroller_pause02.png -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/mediacontroller_play01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/mediacontroller_play01.png -------------------------------------------------------------------------------- /vitamio/res/drawable-hdpi/mediacontroller_play02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-hdpi/mediacontroller_play02.png -------------------------------------------------------------------------------- /vitamio/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /vitamio/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_control_disabled_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_control_disabled_holo.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_control_focused_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_control_focused_holo.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_control_normal_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_control_normal_holo.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_control_pressed_holo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_control_pressed_holo.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_primary_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_primary_holo.9.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_secondary_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_secondary_holo.9.png -------------------------------------------------------------------------------- /vitamio/res/drawable-xhdpi/scrubber_track_holo_dark.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/drawable-xhdpi/scrubber_track_holo_dark.9.png -------------------------------------------------------------------------------- /vitamio/res/drawable/mediacontroller_pause_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /vitamio/res/drawable/mediacontroller_play_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /vitamio/res/drawable/scrubber_control_selector_holo.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /vitamio/res/drawable/scrubber_progress_horizontal_holo_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 17 | 18 | 21 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /vitamio/res/layout/mediacontroller.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 20 | 21 | 29 | 30 | 33 | 34 | 41 | 42 | 49 | 50 | 51 | 59 | 60 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /vitamio/res/raw/libarm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaoba/BlueVideoPlayer/fafd9d63bbbcb971660399460ead2c32a2e690b6/vitamio/res/raw/libarm.so -------------------------------------------------------------------------------- /vitamio/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VitamioLibrary 5 | Initializing decoders… 6 | Vitamio tools 7 | Access Vitamio package and resources. 8 | Receive Vitamio messages 9 | Receive all broadcasts from Vitamio service. 10 | Write Vitamio providers 11 | Delete, update or create new items in Vitamio providers. 12 | 13 | Cannot play video 14 | Sorry, this video is not valid for streaming to 15 | this device. 16 | 17 | Sorry, this video cannot be played. 18 | OK 19 | Play/Pause 20 | 21 | -------------------------------------------------------------------------------- /vitamio/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/LibsChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio; 18 | 19 | import android.app.Activity; 20 | import android.content.Intent; 21 | 22 | /** 23 | * LibsChecker is a wrapper of {@link Vitamio}, it helps to initialize Vitamio 24 | * easily. 25 | *

26 | *

27 |  * public void onCreate(Bundle b) {
28 |  * 	super.onCreate(b);
29 |  * 	if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
30 |  * 		return;
31 |  *
32 |  * 	// Code using Vitamio should go below {@link LibsChecker#checkVitamioLibs}
33 |  * }
34 |  * 
35 | */ 36 | public final class LibsChecker { 37 | public static final String FROM_ME = "fromVitamioInitActivity"; 38 | 39 | public static final boolean checkVitamioLibs(Activity ctx) { 40 | if (!Vitamio.isInitialized(ctx) && !ctx.getIntent().getBooleanExtra(FROM_ME, false)) { 41 | Intent i = new Intent(); 42 | i.setClassName(Vitamio.getVitamioPackage(), "io.vov.vitamio.activity.InitActivity"); 43 | i.putExtras(ctx.getIntent()); 44 | i.setData(ctx.getIntent().getData()); 45 | i.putExtra("package", ctx.getPackageName()); 46 | i.putExtra("className", ctx.getClass().getName()); 47 | ctx.startActivity(i); 48 | ctx.finish(); 49 | return false; 50 | } 51 | return true; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/MediaFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio; 19 | 20 | import java.util.HashMap; 21 | import java.util.Iterator; 22 | 23 | 24 | public class MediaFile { 25 | public static final int FILE_TYPE_MP3 = 1; 26 | public static final int FILE_TYPE_M4A = 2; 27 | public static final int FILE_TYPE_WAV = 3; 28 | public static final int FILE_TYPE_AMR = 4; 29 | public static final int FILE_TYPE_AWB = 5; 30 | public static final int FILE_TYPE_WMA = 6; 31 | public static final int FILE_TYPE_OGG = 7; 32 | public static final int FILE_TYPE_AAC = 8; 33 | public static final int FILE_TYPE_MKA = 9; 34 | public static final int FILE_TYPE_MID = 10; 35 | public static final int FILE_TYPE_SMF = 11; 36 | public static final int FILE_TYPE_IMY = 12; 37 | public static final int FILE_TYPE_APE = 13; 38 | public static final int FILE_TYPE_FLAC = 14; 39 | public static final int FILE_TYPE_MP4 = 701; 40 | public static final int FILE_TYPE_M4V = 702; 41 | public static final int FILE_TYPE_3GPP = 703; 42 | public static final int FILE_TYPE_3GPP2 = 704; 43 | public static final int FILE_TYPE_WMV = 705; 44 | public static final int FILE_TYPE_ASF = 706; 45 | public static final int FILE_TYPE_MKV = 707; 46 | public static final int FILE_TYPE_MP2TS = 708; 47 | public static final int FILE_TYPE_FLV = 709; 48 | public static final int FILE_TYPE_MOV = 710; 49 | public static final int FILE_TYPE_RM = 711; 50 | public static final int FILE_TYPE_DVD = 712; 51 | public static final int FILE_TYPE_DIVX = 713; 52 | public static final int FILE_TYPE_OGV = 714; 53 | public static final int FILE_TYPE_VIVO = 715; 54 | public static final int FILE_TYPE_WTV = 716; 55 | public static final int FILE_TYPE_AVS = 717; 56 | public static final int FILE_TYPE_SWF = 718; 57 | public static final int FILE_TYPE_RAW = 719; 58 | protected final static String sFileExtensions; 59 | private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3; 60 | private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC; 61 | private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4; 62 | private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_RAW; 63 | private static HashMap sFileTypeMap = new HashMap(); 64 | private static HashMap sMimeTypeMap = new HashMap(); 65 | 66 | static { 67 | // addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg"); 68 | // addFileType("M4A", FILE_TYPE_M4A, "audio/mp4"); 69 | // addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav"); 70 | // addFileType("AMR", FILE_TYPE_AMR, "audio/amr"); 71 | // addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb"); 72 | // addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma"); 73 | // addFileType("OGG", FILE_TYPE_OGG, "application/ogg"); 74 | // addFileType("OGA", FILE_TYPE_OGG, "application/ogg"); 75 | // addFileType("AAC", FILE_TYPE_AAC, "audio/aac"); 76 | // addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska"); 77 | // addFileType("MID", FILE_TYPE_MID, "audio/midi"); 78 | // addFileType("MIDI", FILE_TYPE_MID, "audio/midi"); 79 | // addFileType("XMF", FILE_TYPE_MID, "audio/midi"); 80 | // addFileType("RTTTL", FILE_TYPE_MID, "audio/midi"); 81 | // addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi"); 82 | // addFileType("IMY", FILE_TYPE_IMY, "audio/imelody"); 83 | // addFileType("RTX", FILE_TYPE_MID, "audio/midi"); 84 | // addFileType("OTA", FILE_TYPE_MID, "audio/midi"); 85 | // addFileType("APE", FILE_TYPE_APE, "audio/x-ape"); 86 | // addFileType("FLAC", FILE_TYPE_FLAC, "audio/flac"); 87 | 88 | addFileType("M1V", FILE_TYPE_MP4, "video/mpeg"); 89 | addFileType("MP2", FILE_TYPE_MP4, "video/mpeg"); 90 | addFileType("MPE", FILE_TYPE_MP4, "video/mpeg"); 91 | addFileType("MPG", FILE_TYPE_MP4, "video/mpeg"); 92 | addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg"); 93 | addFileType("MP4", FILE_TYPE_MP4, "video/mp4"); 94 | addFileType("M4V", FILE_TYPE_M4V, "video/mp4"); 95 | addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp"); 96 | addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp"); 97 | addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2"); 98 | addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2"); 99 | addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska"); 100 | addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska"); 101 | addFileType("MTS", FILE_TYPE_MP2TS, "video/mp2ts"); 102 | addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts"); 103 | addFileType("TP", FILE_TYPE_MP2TS, "video/mp2ts"); 104 | addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv"); 105 | addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf"); 106 | addFileType("ASX", FILE_TYPE_ASF, "video/x-ms-asf"); 107 | addFileType("FLV", FILE_TYPE_FLV, "video/x-flv"); 108 | addFileType("F4V", FILE_TYPE_FLV, "video/x-flv"); 109 | addFileType("HLV", FILE_TYPE_FLV, "video/x-flv"); 110 | addFileType("MOV", FILE_TYPE_MOV, "video/quicktime"); 111 | addFileType("QT", FILE_TYPE_MOV, "video/quicktime"); 112 | addFileType("RM", FILE_TYPE_RM, "video/x-pn-realvideo"); 113 | addFileType("RMVB", FILE_TYPE_RM, "video/x-pn-realvideo"); 114 | addFileType("VOB", FILE_TYPE_DVD, "video/dvd"); 115 | addFileType("DAT", FILE_TYPE_DVD, "video/dvd"); 116 | addFileType("AVI", FILE_TYPE_DIVX, "video/x-divx"); 117 | addFileType("OGV", FILE_TYPE_OGV, "video/ogg"); 118 | addFileType("OGG", FILE_TYPE_OGV, "video/ogg"); 119 | addFileType("VIV", FILE_TYPE_VIVO, "video/vnd.vivo"); 120 | addFileType("VIVO", FILE_TYPE_VIVO, "video/vnd.vivo"); 121 | addFileType("WTV", FILE_TYPE_WTV, "video/wtv"); 122 | addFileType("AVS", FILE_TYPE_AVS, "video/avs-video"); 123 | addFileType("SWF", FILE_TYPE_SWF, "video/x-shockwave-flash"); 124 | addFileType("YUV", FILE_TYPE_RAW, "video/x-raw-yuv"); 125 | 126 | StringBuilder builder = new StringBuilder(); 127 | Iterator iterator = sFileTypeMap.keySet().iterator(); 128 | 129 | while (iterator.hasNext()) { 130 | if (builder.length() > 0) 131 | builder.append(','); 132 | builder.append(iterator.next()); 133 | } 134 | sFileExtensions = builder.toString(); 135 | } 136 | 137 | static void addFileType(String extension, int fileType, String mimeType) { 138 | sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType)); 139 | sMimeTypeMap.put(mimeType, Integer.valueOf(fileType)); 140 | } 141 | 142 | public static boolean isAudioFileType(int fileType) { 143 | return (fileType >= FIRST_AUDIO_FILE_TYPE && fileType <= LAST_AUDIO_FILE_TYPE); 144 | } 145 | 146 | public static boolean isVideoFileType(int fileType) { 147 | return (fileType >= FIRST_VIDEO_FILE_TYPE && fileType <= LAST_VIDEO_FILE_TYPE); 148 | } 149 | 150 | public static MediaFileType getFileType(String path) { 151 | int lastDot = path.lastIndexOf("."); 152 | if (lastDot < 0) 153 | return null; 154 | return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase()); 155 | } 156 | 157 | public static int getFileTypeForMimeType(String mimeType) { 158 | Integer value = sMimeTypeMap.get(mimeType); 159 | return (value == null ? 0 : value.intValue()); 160 | } 161 | 162 | protected static class MediaFileType { 163 | int fileType; 164 | String mimeType; 165 | 166 | MediaFileType(int fileType, String mimeType) { 167 | this.fileType = fileType; 168 | this.mimeType = mimeType; 169 | } 170 | } 171 | 172 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/MediaMetadataRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio; 19 | 20 | import android.content.ContentResolver; 21 | import android.content.Context; 22 | import android.content.res.AssetFileDescriptor; 23 | import android.graphics.Bitmap; 24 | import android.net.Uri; 25 | import android.util.Log; 26 | 27 | import java.io.FileDescriptor; 28 | import java.io.IOException; 29 | 30 | import io.vov.vitamio.utils.FileUtils; 31 | 32 | /** 33 | * MediaMetadataRetriever is used to get meta data from any media file 34 | *

35 | *

 36 |  * MediaMetadataRetriever mmr = new MediaMetadataRetriever(this);
 37 |  * mmr.setDataSource(this, mediaUri);
 38 |  * String title = mmr.extractMetadata(METADATA_KEY_TITLE);
 39 |  * Bitmap frame = mmr.getFrameAtTime(-1);
 40 |  * 
41 | */ 42 | public class MediaMetadataRetriever { 43 | /** 44 | * The metadata key to retrieve the information about the album title 45 | * of the data source. 46 | */ 47 | public static final String METADATA_KEY_ALBUM = "album"; 48 | /** 49 | * The metadata key to retrieve the information about the artist of 50 | * the data source. 51 | */ 52 | public static final String METADATA_KEY_ARTIST = "artist"; 53 | /** 54 | * The metadata key to retrieve the information about the author of 55 | * the data source. 56 | */ 57 | public static final String METADATA_KEY_AUTHOR = "author"; 58 | /** 59 | * The metadata key to retrieve the information about the composer of 60 | * the data source. 61 | */ 62 | public static final String METADATA_KEY_COMPOSER = "composer"; 63 | /** 64 | * The metadata key to retrieve the content type or genre of the data 65 | * source. 66 | */ 67 | public static final String METADATA_KEY_GENRE = "genre"; 68 | /** 69 | * The metadata key to retrieve the data source title. 70 | */ 71 | public static final String METADATA_KEY_TITLE = "title"; 72 | /** 73 | * The metadata key to retrieve the playback duration of the data source. 74 | */ 75 | public static final String METADATA_KEY_DURATION = "duration"; 76 | /** 77 | * If the media contains video, this key retrieves its width. 78 | */ 79 | public static final String METADATA_KEY_VIDEO_WIDTH = "width"; 80 | /** 81 | * If the media contains video, this key retrieves its height. 82 | */ 83 | public static final String METADATA_KEY_VIDEO_HEIGHT = "height"; 84 | 85 | static { 86 | String LIB_ROOT = Vitamio.getLibraryPath(); 87 | Log.i("LIB ROOT: %s", LIB_ROOT); 88 | System.load(LIB_ROOT + "libstlport_shared.so"); 89 | System.load(LIB_ROOT + "libvscanner.so"); 90 | loadFFmpeg_native(LIB_ROOT + "libffmpeg.so"); 91 | } 92 | 93 | private Context mContext; 94 | private AssetFileDescriptor mFD = null; 95 | 96 | public MediaMetadataRetriever(Context ctx) { 97 | mContext = ctx; 98 | native_init(); 99 | } 100 | 101 | private static native boolean loadFFmpeg_native(String ffmpegPath); 102 | 103 | public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { 104 | if (context == null || uri == null) 105 | throw new IllegalArgumentException(); 106 | String scheme = uri.getScheme(); 107 | if (scheme == null || scheme.equals("file")) { 108 | setDataSource(FileUtils.getPath(uri.toString())); 109 | return; 110 | } 111 | 112 | try { 113 | ContentResolver resolver = context.getContentResolver(); 114 | mFD = resolver.openAssetFileDescriptor(uri, "r"); 115 | if (mFD == null) 116 | return; 117 | setDataSource(mFD.getParcelFileDescriptor().getFileDescriptor()); 118 | return; 119 | } catch (Exception e) { 120 | closeFD(); 121 | } 122 | Log.e("Couldn't open file on client side, trying server side %s", uri.toString()); 123 | setDataSource(uri.toString()); 124 | return; 125 | } 126 | 127 | public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException; 128 | 129 | /* 130 | * Do not change these metadata key values without updating their 131 | * counterparts in c file 132 | */ 133 | 134 | public native void setDataSource(FileDescriptor fd) throws IOException, IllegalArgumentException, IllegalStateException; 135 | 136 | /** 137 | * Call this method after setDataSource(). This method retrieves the 138 | * meta data value associated with the keyCode. 139 | *

140 | * The keyCode currently supported is listed below as METADATA_XXX 141 | * constants. With any other value, it returns a null pointer. 142 | * 143 | * @param keyCode One of the constants listed below at the end of the class. 144 | * @return The meta data value associate with the given keyCode on success; 145 | * null on failure. 146 | */ 147 | public native String extractMetadata(String keyCode) throws IllegalStateException; 148 | 149 | public native Bitmap getFrameAtTime(long timeUs) throws IllegalStateException; 150 | 151 | private native void _release(); 152 | 153 | public void release() { 154 | _release(); 155 | closeFD(); 156 | } 157 | 158 | private native final void native_init(); 159 | 160 | private native final void native_finalize(); 161 | 162 | @Override 163 | protected void finalize() throws Throwable { 164 | try { 165 | native_finalize(); 166 | } finally { 167 | super.finalize(); 168 | } 169 | } 170 | 171 | private void closeFD() { 172 | if (mFD != null) { 173 | try { 174 | mFD.close(); 175 | } catch (IOException e) { 176 | } 177 | mFD = null; 178 | } 179 | } 180 | 181 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/MediaScannerClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio; 19 | 20 | /** 21 | * DON'T TOUCH THIS FILE IF YOU DON'T KNOW THE MediaScanner PROCEDURE!!! 22 | */ 23 | public interface MediaScannerClient { 24 | void scanFile(String path, long lastModified, long fileSize); 25 | 26 | void addNoMediaFolder(String path); 27 | 28 | void handleStringTag(String name, byte[] value, String valueEncoding); 29 | 30 | void setMimeType(String mimeType); 31 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/Metadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio; 19 | 20 | import android.util.SparseArray; 21 | 22 | import java.io.UnsupportedEncodingException; 23 | import java.util.Locale; 24 | import java.util.Map; 25 | 26 | /** 27 | * See {@link io.vov.vitamio.MediaPlayer#getMetadata()} 28 | */ 29 | public class Metadata { 30 | public static final int ANY = 0; 31 | public static final int TITLE = 1; // String 32 | public static final int COMMENT = 2; // String 33 | public static final int COPYRIGHT = 3; // String 34 | public static final int ALBUM = 4; // String 35 | public static final int ARTIST = 5; // String 36 | public static final int AUTHOR = 6; // String 37 | public static final int COMPOSER = 7; // String 38 | public static final int GENRE = 8; // String 39 | public static final int DATE = 9; // Date 40 | public static final int DURATION = 10; // Integer(milliseconds) 41 | public static final int CD_TRACK_NUM = 11; // Integer (1-based) 42 | public static final int CD_TRACK_MAX = 12; // Integer 43 | public static final int RATING = 13; // String 44 | public static final int ALBUM_ART = 14; // byte[] 45 | public static final int VIDEO_FRAME = 15; // Bitmap 46 | public static final int LENGTH = 16; // Integer (bytes) 47 | public static final int BIT_RATE = 17; // Integer 48 | public static final int AUDIO_BIT_RATE = 18; // Integer 49 | public static final int VIDEO_BIT_RATE = 19; // Integer 50 | public static final int AUDIO_SAMPLE_RATE = 20; // Integer 51 | public static final int VIDEO_FRAME_RATE = 21; // Float 52 | // See RFC2046 and RFC4281. 53 | public static final int MIME_TYPE = 22; // String 54 | public static final int AUDIO_CODEC = 23; // String 55 | public static final int VIDEO_CODEC = 24; // String 56 | public static final int VIDEO_HEIGHT = 25; // Integer 57 | public static final int VIDEO_WIDTH = 26; // Integer 58 | public static final int NUM_TRACKS = 27; // Integer 59 | public static final int DRM_CRIPPLED = 28; // Boolean 60 | public static final int PAUSE_AVAILABLE = 29; // Boolean 61 | public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean 62 | public static final int SEEK_FORWARD_AVAILABLE = 31; // Boolean 63 | public static final int SEEK_AVAILABLE = 32; // Boolean 64 | private static final int LAST_SYSTEM = 32; 65 | private static final int FIRST_CUSTOM = 8192; 66 | private SparseArray mMeta = new SparseArray(); 67 | private String mEncoding = "UTF-8"; 68 | 69 | public boolean parse(Map meta, String encoding) { 70 | String key = null; 71 | byte[] value = null; 72 | mEncoding = encoding; 73 | for (byte[] keyBytes : meta.keySet()) { 74 | try { 75 | key = new String(keyBytes, mEncoding).trim().toLowerCase(Locale.US); 76 | } catch (UnsupportedEncodingException e) { 77 | key = new String(keyBytes).trim().toLowerCase(Locale.US); 78 | } 79 | value = meta.get(keyBytes); 80 | if (key.equals("title")) { 81 | mMeta.put(TITLE, value); 82 | } else if (key.equals("comment")) { 83 | mMeta.put(COMMENT, value); 84 | } else if (key.equals("copyright")) { 85 | mMeta.put(COPYRIGHT, value); 86 | } else if (key.equals("album")) { 87 | mMeta.put(ALBUM, value); 88 | } else if (key.equals("artist")) { 89 | mMeta.put(ARTIST, value); 90 | } else if (key.equals("author")) { 91 | mMeta.put(AUTHOR, value); 92 | } else if (key.equals("composer")) { 93 | mMeta.put(COMPOSER, value); 94 | } else if (key.equals("genre")) { 95 | mMeta.put(GENRE, value); 96 | } else if (key.equals("creation_time") || key.equals("date")) { 97 | mMeta.put(DATE, value); 98 | } else if (key.equals("duration")) { 99 | mMeta.put(DURATION, value); 100 | } else if (key.equals("length")) { 101 | mMeta.put(LENGTH, value); 102 | } else if (key.equals("bit_rate")) { 103 | mMeta.put(BIT_RATE, value); 104 | } else if (key.equals("audio_bit_rate")) { 105 | mMeta.put(AUDIO_BIT_RATE, value); 106 | } else if (key.equals("video_bit_rate")) { 107 | mMeta.put(VIDEO_BIT_RATE, value); 108 | } else if (key.equals("audio_sample_rate")) { 109 | mMeta.put(AUDIO_SAMPLE_RATE, value); 110 | } else if (key.equals("video_frame_rate")) { 111 | mMeta.put(VIDEO_FRAME_RATE, value); 112 | } else if (key.equals("format")) { 113 | mMeta.put(MIME_TYPE, value); 114 | } else if (key.equals("audio_codec")) { 115 | mMeta.put(AUDIO_CODEC, value); 116 | } else if (key.equals("video_codec")) { 117 | mMeta.put(VIDEO_CODEC, value); 118 | } else if (key.equals("video_height")) { 119 | mMeta.put(VIDEO_HEIGHT, value); 120 | } else if (key.equals("video_width")) { 121 | mMeta.put(VIDEO_WIDTH, value); 122 | } else if (key.equals("num_tracks")) { 123 | mMeta.put(NUM_TRACKS, value); 124 | } else if (key.equals("cap_pause")) { 125 | mMeta.put(PAUSE_AVAILABLE, value); 126 | } else if (key.equals("cap_seek")) { 127 | mMeta.put(SEEK_AVAILABLE, value); 128 | } 129 | } 130 | 131 | if (BuildConfig.DEBUG) { 132 | android.util.Log.i("Vitamio[Metadata]", "title:\t\t" + getString(TITLE)); 133 | android.util.Log.i("Vitamio[Metadata]", "comment:\t\t" + getString(COMMENT)); 134 | android.util.Log.i("Vitamio[Metadata]", "copyright:\t\t" + getString(COPYRIGHT)); 135 | android.util.Log.i("Vitamio[Metadata]", "album:\t\t" + getString(ALBUM)); 136 | android.util.Log.i("Vitamio[Metadata]", "artist:\t\t" + getString(ARTIST)); 137 | android.util.Log.i("Vitamio[Metadata]", "composer:\t\t" + getString(COMPOSER)); 138 | android.util.Log.i("Vitamio[Metadata]", "genre:\t\t" + getString(GENRE)); 139 | android.util.Log.i("Vitamio[Metadata]", "date:\t\t" + getString(DATE)); 140 | android.util.Log.i("Vitamio[Metadata]", "duration:\t\t" + getLong(DURATION)); 141 | android.util.Log.i("Vitamio[Metadata]", "length:\t\t" + getLong(LENGTH)); 142 | android.util.Log.i("Vitamio[Metadata]", "bit_rate:\t\t" + getInt(BIT_RATE)); 143 | android.util.Log.i("Vitamio[Metadata]", "audio_bit_rate:\t" + getInt(AUDIO_BIT_RATE)); 144 | android.util.Log.i("Vitamio[Metadata]", "video_bit_rate:\t" + getInt(VIDEO_BIT_RATE)); 145 | android.util.Log.i("Vitamio[Metadata]", "audio_sample_rate:\t" + getInt(AUDIO_SAMPLE_RATE)); 146 | android.util.Log.i("Vitamio[Metadata]", "video_frame_rate:\t" + getDouble(VIDEO_FRAME_RATE)); 147 | android.util.Log.i("Vitamio[Metadata]", "format:\t\t" + getString(MIME_TYPE)); 148 | android.util.Log.i("Vitamio[Metadata]", "audio_codec:\t" + getString(AUDIO_CODEC)); 149 | android.util.Log.i("Vitamio[Metadata]", "video_codec:\t" + getString(VIDEO_CODEC)); 150 | android.util.Log.i("Vitamio[Metadata]", "video_height:\t" + getInt(VIDEO_HEIGHT)); 151 | android.util.Log.i("Vitamio[Metadata]", "video_width:\t" + getInt(VIDEO_WIDTH)); 152 | android.util.Log.i("Vitamio[Metadata]", "num_tracks:\t\t" + getInt(NUM_TRACKS)); 153 | android.util.Log.i("Vitamio[Metadata]", "cap_pause:\t\t" + getBoolean(PAUSE_AVAILABLE)); 154 | android.util.Log.i("Vitamio[Metadata]", "cap_seek:\t\t" + getBoolean(SEEK_AVAILABLE)); 155 | } 156 | 157 | return true; 158 | } 159 | 160 | public boolean has(final int metadataId) { 161 | if (!checkMetadataId(metadataId)) { 162 | throw new IllegalArgumentException("Invalid key: " + metadataId); 163 | } 164 | return mMeta.indexOfKey(metadataId) >= 0; 165 | } 166 | 167 | public String getString(final int key) { 168 | byte[] value = mMeta.get(key); 169 | if (value == null) { 170 | return null; 171 | } 172 | try { 173 | return new String(value, mEncoding); 174 | } catch (UnsupportedEncodingException e) { 175 | return new String(value); 176 | } 177 | } 178 | 179 | public int getInt(final int key) { 180 | try { 181 | return Integer.parseInt(getString(key)); 182 | } catch (Exception e) { 183 | return -1; 184 | } 185 | } 186 | 187 | public boolean getBoolean(final int key) { 188 | try { 189 | return Boolean.parseBoolean(getString(key)); 190 | } catch (Exception e) { 191 | return false; 192 | } 193 | } 194 | 195 | public long getLong(final int key) { 196 | try { 197 | return Long.parseLong(getString(key)); 198 | } catch (Exception e) { 199 | return -1; 200 | } 201 | } 202 | 203 | public double getDouble(final int key) { 204 | try { 205 | return Double.parseDouble(getString(key)); 206 | } catch (Exception e) { 207 | return -1; 208 | } 209 | } 210 | 211 | public byte[] getByteArray(final int key) { 212 | return mMeta.get(key); 213 | } 214 | 215 | private boolean checkMetadataId(final int val) { 216 | return !(val <= ANY || (LAST_SYSTEM < val && val < FIRST_CUSTOM)); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/ThumbnailUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio; 19 | 20 | import android.content.Context; 21 | import android.graphics.Bitmap; 22 | import android.graphics.Canvas; 23 | import android.graphics.Matrix; 24 | import android.graphics.Rect; 25 | 26 | import io.vov.vitamio.provider.MediaStore.Video; 27 | 28 | /** 29 | * ThumbnailUtils is a wrapper of MediaMetadataRetriever to retrive a thumbnail 30 | * of video file. 31 | *

32 | *

 33 |  * Bitmap thumb = ThumbnailUtils.createVideoThumbnail(this, videoPath, MINI_KIND);
 34 |  * 
35 | */ 36 | public class ThumbnailUtils { 37 | public static final int OPTIONS_RECYCLE_INPUT = 0x2; 38 | public static final int TARGET_SIZE_MINI_THUMBNAIL_WIDTH = 426; 39 | public static final int TARGET_SIZE_MINI_THUMBNAIL_HEIGHT = 320; 40 | public static final int TARGET_SIZE_MICRO_THUMBNAIL_WIDTH = 212; 41 | public static final int TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT = 160; 42 | private static final int OPTIONS_NONE = 0x0; 43 | private static final int OPTIONS_SCALE_UP = 0x1; 44 | 45 | public static Bitmap createVideoThumbnail(Context ctx, String filePath, int kind) { 46 | if (!Vitamio.isInitialized(ctx)) { 47 | return null; 48 | } 49 | Bitmap bitmap = null; 50 | MediaMetadataRetriever retriever = null; 51 | try { 52 | retriever = new MediaMetadataRetriever(ctx); 53 | retriever.setDataSource(filePath); 54 | bitmap = retriever.getFrameAtTime(-1); 55 | } catch (Exception ex) { 56 | } finally { 57 | try { 58 | retriever.release(); 59 | } catch (RuntimeException ex) { 60 | } 61 | } 62 | 63 | if (bitmap != null) { 64 | if (kind == Video.Thumbnails.MICRO_KIND) 65 | bitmap = extractThumbnail(bitmap, TARGET_SIZE_MICRO_THUMBNAIL_WIDTH, TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT, OPTIONS_RECYCLE_INPUT); 66 | else if (kind == Video.Thumbnails.MINI_KIND) 67 | bitmap = extractThumbnail(bitmap, TARGET_SIZE_MINI_THUMBNAIL_WIDTH, TARGET_SIZE_MINI_THUMBNAIL_HEIGHT, OPTIONS_RECYCLE_INPUT); 68 | } 69 | return bitmap; 70 | } 71 | 72 | public static Bitmap extractThumbnail(Bitmap source, int width, int height) { 73 | return extractThumbnail(source, width, height, OPTIONS_NONE); 74 | } 75 | 76 | public static Bitmap extractThumbnail(Bitmap source, int width, int height, int options) { 77 | if (source == null) 78 | return null; 79 | 80 | float scale; 81 | if (source.getWidth() < source.getHeight()) 82 | scale = width / (float) source.getWidth(); 83 | else 84 | scale = height / (float) source.getHeight(); 85 | Matrix matrix = new Matrix(); 86 | matrix.setScale(scale, scale); 87 | Bitmap thumbnail = transform(matrix, source, width, height, OPTIONS_SCALE_UP | options); 88 | return thumbnail; 89 | } 90 | 91 | private static Bitmap transform(Matrix scaler, Bitmap source, int targetWidth, int targetHeight, int options) { 92 | boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0; 93 | boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0; 94 | 95 | int deltaX = source.getWidth() - targetWidth; 96 | int deltaY = source.getHeight() - targetHeight; 97 | if (!scaleUp && (deltaX < 0 || deltaY < 0)) { 98 | Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888); 99 | Canvas c = new Canvas(b2); 100 | 101 | int deltaXHalf = Math.max(0, deltaX / 2); 102 | int deltaYHalf = Math.max(0, deltaY / 2); 103 | Rect src = new Rect(deltaXHalf, deltaYHalf, deltaXHalf + Math.min(targetWidth, source.getWidth()), deltaYHalf + Math.min(targetHeight, source.getHeight())); 104 | int dstX = (targetWidth - src.width()) / 2; 105 | int dstY = (targetHeight - src.height()) / 2; 106 | Rect dst = new Rect(dstX, dstY, targetWidth - dstX, targetHeight - dstY); 107 | c.drawBitmap(source, src, dst, null); 108 | if (recycle) 109 | source.recycle(); 110 | return b2; 111 | } 112 | 113 | float bitmapWidthF = source.getWidth(); 114 | float bitmapHeightF = source.getHeight(); 115 | float bitmapAspect = bitmapWidthF / bitmapHeightF; 116 | float viewAspect = (float) targetWidth / targetHeight; 117 | 118 | float scale = bitmapAspect > viewAspect ? targetHeight / bitmapHeightF : targetWidth / bitmapWidthF; 119 | if (scale < .9F || scale > 1F) 120 | scaler.setScale(scale, scale); 121 | else 122 | scaler = null; 123 | 124 | Bitmap b1; 125 | if (scaler != null) 126 | b1 = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), scaler, true); 127 | else 128 | b1 = source; 129 | 130 | if (recycle && b1 != source) 131 | source.recycle(); 132 | 133 | int dx1 = Math.max(0, b1.getWidth() - targetWidth); 134 | int dy1 = Math.max(0, b1.getHeight() - targetHeight); 135 | 136 | Bitmap b2 = Bitmap.createBitmap(b1, dx1 / 2, dy1 / 2, targetWidth, targetHeight); 137 | 138 | if (b2 != b1 && (recycle || b1 != source)) 139 | b1.recycle(); 140 | 141 | return b2; 142 | } 143 | 144 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/VIntent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio; 18 | 19 | /** 20 | * Common intent actions used by Vitamio component. 21 | */ 22 | public class VIntent { 23 | public static final String ACTION_MEDIA_SCANNER_SCAN_DIRECTORY = "com.yixia.vitamio.action.MEDIA_SCANNER_SCAN_DIRECTORY"; 24 | public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "com.yixia.vitamio.action.MEDIA_SCANNER_SCAN_FILE"; 25 | public static final String ACTION_MEDIA_SCANNER_STARTED = "com.yixia.vitamio.action.MEDIA_SCANNER_STARTED"; 26 | public static final String ACTION_MEDIA_SCANNER_FINISHED = "com.yixia.vitamio.action.MEDIA_SCANNER_FINISHED"; 27 | } 28 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/VitamioLicense.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio; 18 | 19 | /** 20 | * DON'T MODIFY THIS FILE IF YOU WANT TO USE VITAMIO 21 | */ 22 | public class VitamioLicense { 23 | public static final String LICENSE = "Copyright (c) YIXIA (http://yixia.com).\nTHIS SOFTWARE (Vitamio) IS WORK OF YIXIA (http://yixia.com)"; 24 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/activity/InitActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio.activity; 18 | 19 | import android.app.Activity; 20 | import android.app.ProgressDialog; 21 | import android.content.Context; 22 | import android.content.Intent; 23 | import android.os.AsyncTask; 24 | import android.os.Bundle; 25 | import android.os.Handler; 26 | import android.os.Message; 27 | import android.view.WindowManager; 28 | 29 | import java.lang.ref.WeakReference; 30 | 31 | import io.vov.vitamio.R; 32 | import io.vov.vitamio.Vitamio; 33 | 34 | public class InitActivity extends Activity { 35 | public static final String FROM_ME = "fromVitamioInitActivity"; 36 | private ProgressDialog mPD; 37 | private UIHandler uiHandler; 38 | 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 42 | uiHandler = new UIHandler(this); 43 | 44 | new AsyncTask() { 45 | @Override 46 | protected void onPreExecute() { 47 | mPD = new ProgressDialog(InitActivity.this); 48 | mPD.setCancelable(false); 49 | mPD.setMessage(InitActivity.this.getString(R.string.vitamio_init_decoders)); 50 | mPD.show(); 51 | } 52 | 53 | @Override 54 | protected Boolean doInBackground(Object... params) { 55 | return Vitamio.initialize(InitActivity.this, R.raw.libarm); 56 | } 57 | 58 | @Override 59 | protected void onPostExecute(Boolean inited) { 60 | if (inited) { 61 | uiHandler.sendEmptyMessage(0); 62 | } 63 | } 64 | 65 | }.execute(); 66 | } 67 | 68 | private static class UIHandler extends Handler { 69 | private WeakReference mContext; 70 | 71 | public UIHandler(Context c) { 72 | mContext = new WeakReference(c); 73 | } 74 | 75 | public void handleMessage(Message msg) { 76 | InitActivity ctx = (InitActivity) mContext.get(); 77 | switch (msg.what) { 78 | case 0: 79 | ctx.mPD.dismiss(); 80 | Intent src = ctx.getIntent(); 81 | Intent i = new Intent(); 82 | i.setClassName(src.getStringExtra("package"), src.getStringExtra("className")); 83 | i.setData(src.getData()); 84 | i.putExtras(src); 85 | i.putExtra(FROM_ME, true); 86 | ctx.startActivity(i); 87 | ctx.finish(); 88 | break; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/provider/MiniThumbFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2006 The Android Open Source Project 3 | * Copyright (C) 2013 YIXIA.COM 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.vov.vitamio.provider; 19 | 20 | import android.net.Uri; 21 | import android.os.Environment; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.io.RandomAccessFile; 26 | import java.nio.ByteBuffer; 27 | import java.nio.channels.FileChannel; 28 | import java.nio.channels.FileLock; 29 | import java.util.Hashtable; 30 | 31 | import io.vov.vitamio.provider.MediaStore.Video; 32 | import io.vov.vitamio.utils.Log; 33 | 34 | public class MiniThumbFile { 35 | protected static final int BYTES_PER_MINTHUMB = 10000; 36 | private static final int MINI_THUMB_DATA_FILE_VERSION = 7; 37 | private static final int HEADER_SIZE = 1 + 8 + 4; 38 | private static Hashtable sThumbFiles = new Hashtable(); 39 | private Uri mUri; 40 | private RandomAccessFile mMiniThumbFile; 41 | private FileChannel mChannel; 42 | private ByteBuffer mBuffer; 43 | 44 | public MiniThumbFile(Uri uri) { 45 | mUri = uri; 46 | mBuffer = ByteBuffer.allocateDirect(BYTES_PER_MINTHUMB); 47 | } 48 | 49 | protected static synchronized void reset() { 50 | for (MiniThumbFile file : sThumbFiles.values()) 51 | file.deactivate(); 52 | sThumbFiles.clear(); 53 | } 54 | 55 | protected static synchronized MiniThumbFile instance(Uri uri) { 56 | String type = uri.getPathSegments().get(0); 57 | MiniThumbFile file = sThumbFiles.get(type); 58 | if (file == null) { 59 | file = new MiniThumbFile(Uri.parse(MediaStore.CONTENT_AUTHORITY_SLASH + type + "/media")); 60 | sThumbFiles.put(type, file); 61 | } 62 | 63 | return file; 64 | } 65 | 66 | private String randomAccessFilePath(int version) { 67 | String directoryName = Environment.getExternalStorageDirectory().toString() + "/" + Video.Thumbnails.THUMBNAILS_DIRECTORY; 68 | return directoryName + "/.thumbdata" + version + "-" + mUri.hashCode(); 69 | } 70 | 71 | private void removeOldFile() { 72 | String oldPath = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION - 1); 73 | File oldFile = new File(oldPath); 74 | if (oldFile.exists()) { 75 | try { 76 | oldFile.delete(); 77 | } catch (SecurityException ex) { 78 | } 79 | } 80 | } 81 | 82 | private RandomAccessFile miniThumbDataFile() { 83 | if (mMiniThumbFile == null) { 84 | removeOldFile(); 85 | String path = randomAccessFilePath(MINI_THUMB_DATA_FILE_VERSION); 86 | File directory = new File(path).getParentFile(); 87 | if (!directory.isDirectory()) { 88 | if (!directory.mkdirs()) 89 | Log.e("Unable to create .thumbnails directory %s", directory.toString()); 90 | } 91 | File f = new File(path); 92 | try { 93 | mMiniThumbFile = new RandomAccessFile(f, "rw"); 94 | } catch (IOException ex) { 95 | try { 96 | mMiniThumbFile = new RandomAccessFile(f, "r"); 97 | } catch (IOException ex2) { 98 | } 99 | } 100 | 101 | if (mMiniThumbFile != null) 102 | mChannel = mMiniThumbFile.getChannel(); 103 | } 104 | return mMiniThumbFile; 105 | } 106 | 107 | protected synchronized void deactivate() { 108 | if (mMiniThumbFile != null) { 109 | try { 110 | mMiniThumbFile.close(); 111 | mMiniThumbFile = null; 112 | } catch (IOException ex) { 113 | } 114 | } 115 | } 116 | 117 | protected synchronized long getMagic(long id) { 118 | RandomAccessFile r = miniThumbDataFile(); 119 | if (r != null) { 120 | long pos = id * BYTES_PER_MINTHUMB; 121 | FileLock lock = null; 122 | try { 123 | mBuffer.clear(); 124 | mBuffer.limit(1 + 8); 125 | 126 | lock = mChannel.lock(pos, 1 + 8, true); 127 | if (mChannel.read(mBuffer, pos) == 9) { 128 | mBuffer.position(0); 129 | if (mBuffer.get() == 1) 130 | return mBuffer.getLong(); 131 | } 132 | } catch (IOException ex) { 133 | Log.e("Got exception checking file magic: ", ex); 134 | } catch (RuntimeException ex) { 135 | Log.e("Got exception when reading magic, id = %d, disk full or mount read-only? %s", id, ex.getClass().toString()); 136 | } finally { 137 | try { 138 | if (lock != null) 139 | lock.release(); 140 | } catch (IOException ex) { 141 | } 142 | } 143 | } 144 | return 0; 145 | } 146 | 147 | protected synchronized void saveMiniThumbToFile(byte[] data, long id, long magic) throws IOException { 148 | RandomAccessFile r = miniThumbDataFile(); 149 | if (r == null) 150 | return; 151 | 152 | long pos = id * BYTES_PER_MINTHUMB; 153 | FileLock lock = null; 154 | try { 155 | if (data != null) { 156 | if (data.length > BYTES_PER_MINTHUMB - HEADER_SIZE) 157 | return; 158 | 159 | mBuffer.clear(); 160 | mBuffer.put((byte) 1); 161 | mBuffer.putLong(magic); 162 | mBuffer.putInt(data.length); 163 | mBuffer.put(data); 164 | mBuffer.flip(); 165 | 166 | lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, false); 167 | mChannel.write(mBuffer, pos); 168 | } 169 | } catch (IOException ex) { 170 | Log.e("couldn't save mini thumbnail data for %d; %s", id, ex.getMessage()); 171 | throw ex; 172 | } catch (RuntimeException ex) { 173 | Log.e("couldn't save mini thumbnail data for %d, disk full or mount read-only? %s", id, ex.getClass().toString()); 174 | } finally { 175 | try { 176 | if (lock != null) 177 | lock.release(); 178 | } catch (IOException ex) { 179 | } 180 | } 181 | } 182 | 183 | protected synchronized byte[] getMiniThumbFromFile(long id, byte[] data) { 184 | RandomAccessFile r = miniThumbDataFile(); 185 | if (r == null) 186 | return null; 187 | 188 | long pos = id * BYTES_PER_MINTHUMB; 189 | FileLock lock = null; 190 | try { 191 | mBuffer.clear(); 192 | lock = mChannel.lock(pos, BYTES_PER_MINTHUMB, true); 193 | int size = mChannel.read(mBuffer, pos); 194 | if (size > 1 + 8 + 4) { 195 | mBuffer.position(9); 196 | int length = mBuffer.getInt(); 197 | 198 | if (size >= 1 + 8 + 4 + length && data.length >= length) { 199 | mBuffer.get(data, 0, length); 200 | return data; 201 | } 202 | } 203 | } catch (IOException ex) { 204 | Log.e("got exception when reading thumbnail id = %d, exception: %s", id, ex.getMessage()); 205 | } catch (RuntimeException ex) { 206 | Log.e("Got exception when reading thumbnail, id = %d, disk full or mount read-only? %s", id, ex.getClass().toString()); 207 | } finally { 208 | try { 209 | if (lock != null) 210 | lock.release(); 211 | } catch (IOException ex) { 212 | } 213 | } 214 | return null; 215 | } 216 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/CPU.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import android.os.Build; 19 | import android.text.TextUtils; 20 | 21 | import java.io.BufferedReader; 22 | import java.io.File; 23 | import java.io.FileReader; 24 | import java.io.IOException; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | public class CPU { 29 | public static final int FEATURE_ARM_V5TE = 1 << 0; 30 | public static final int FEATURE_ARM_V6 = 1 << 1; 31 | public static final int FEATURE_ARM_VFP = 1 << 2; 32 | public static final int FEATURE_ARM_V7A = 1 << 3; 33 | public static final int FEATURE_ARM_VFPV3 = 1 << 4; 34 | public static final int FEATURE_ARM_NEON = 1 << 5; 35 | public static final int FEATURE_X86 = 1 << 6; 36 | public static final int FEATURE_MIPS = 1 << 7; 37 | private static final Map cpuinfo = new HashMap(); 38 | private static int cachedFeature = -1; 39 | private static String cachedFeatureString = null; 40 | 41 | public static String getFeatureString() { 42 | getFeature(); 43 | return cachedFeatureString; 44 | } 45 | 46 | public static int getFeature() { 47 | if (cachedFeature > 0) 48 | return getCachedFeature(); 49 | 50 | cachedFeature = FEATURE_ARM_V5TE; 51 | 52 | if (cpuinfo.isEmpty()) { 53 | BufferedReader bis = null; 54 | try { 55 | bis = new BufferedReader(new FileReader(new File("/proc/cpuinfo"))); 56 | String line; 57 | String[] pairs; 58 | while ((line = bis.readLine()) != null) { 59 | if (!line.trim().equals("")) { 60 | pairs = line.split(":"); 61 | if (pairs.length > 1) 62 | cpuinfo.put(pairs[0].trim(), pairs[1].trim()); 63 | } 64 | } 65 | } catch (Exception e) { 66 | Log.e("getCPUFeature", e); 67 | } finally { 68 | try { 69 | if (bis != null) 70 | bis.close(); 71 | } catch (IOException e) { 72 | Log.e("getCPUFeature", e); 73 | } 74 | } 75 | } 76 | 77 | if (!cpuinfo.isEmpty()) { 78 | for (String key : cpuinfo.keySet()) 79 | Log.d("%s:%s", key, cpuinfo.get(key)); 80 | 81 | boolean hasARMv6 = false; 82 | boolean hasARMv7 = false; 83 | 84 | String val = cpuinfo.get("CPU architecture"); 85 | if (!TextUtils.isEmpty(val)) { 86 | try { 87 | int i = StringUtils.convertToInt(val); 88 | Log.d("CPU architecture: %s", i); 89 | if (i >= 7) { 90 | hasARMv6 = true; 91 | hasARMv7 = true; 92 | } else if (i >= 6) { 93 | hasARMv6 = true; 94 | hasARMv7 = false; 95 | } 96 | } catch (NumberFormatException ex) { 97 | Log.e("getCPUFeature", ex); 98 | } 99 | 100 | val = cpuinfo.get("Processor"); 101 | if (val != null && (val.contains("(v7l)") || val.contains("ARMv7"))) { 102 | hasARMv6 = true; 103 | hasARMv7 = true; 104 | } 105 | if (val != null && (val.contains("(v6l)") || val.contains("ARMv6"))) { 106 | hasARMv6 = true; 107 | hasARMv7 = false; 108 | } 109 | 110 | if (hasARMv6) 111 | cachedFeature |= FEATURE_ARM_V6; 112 | if (hasARMv7) 113 | cachedFeature |= FEATURE_ARM_V7A; 114 | 115 | val = cpuinfo.get("Features"); 116 | if (val != null) { 117 | if (val.contains("neon")) 118 | cachedFeature |= FEATURE_ARM_VFP | FEATURE_ARM_VFPV3 | FEATURE_ARM_NEON; 119 | else if (val.contains("vfpv3")) 120 | cachedFeature |= FEATURE_ARM_VFP | FEATURE_ARM_VFPV3; 121 | else if (val.contains("vfp")) 122 | cachedFeature |= FEATURE_ARM_VFP; 123 | } 124 | } else { 125 | String vendor_id = cpuinfo.get("vendor_id"); 126 | String mips = cpuinfo.get("cpu model"); 127 | if (!TextUtils.isEmpty(vendor_id) && vendor_id.contains("GenuineIntel")) { 128 | cachedFeature |= FEATURE_X86; 129 | } else if (!TextUtils.isEmpty(mips) && mips.contains("MIPS")) { 130 | cachedFeature |= FEATURE_MIPS; 131 | } 132 | } 133 | } 134 | 135 | return getCachedFeature(); 136 | } 137 | 138 | private static int getCachedFeature() { 139 | if (cachedFeatureString == null) { 140 | StringBuffer sb = new StringBuffer(); 141 | if ((cachedFeature & FEATURE_ARM_V5TE) > 0) 142 | sb.append("V5TE "); 143 | if ((cachedFeature & FEATURE_ARM_V6) > 0) 144 | sb.append("V6 "); 145 | if ((cachedFeature & FEATURE_ARM_VFP) > 0) 146 | sb.append("VFP "); 147 | if ((cachedFeature & FEATURE_ARM_V7A) > 0) 148 | sb.append("V7A "); 149 | if ((cachedFeature & FEATURE_ARM_VFPV3) > 0) 150 | sb.append("VFPV3 "); 151 | if ((cachedFeature & FEATURE_ARM_NEON) > 0) 152 | sb.append("NEON "); 153 | if ((cachedFeature & FEATURE_X86) > 0) 154 | sb.append("X86 "); 155 | if ((cachedFeature & FEATURE_MIPS) > 0) 156 | sb.append("MIPS "); 157 | cachedFeatureString = sb.toString(); 158 | } 159 | Log.d("GET CPU FATURE: %s", cachedFeatureString); 160 | return cachedFeature; 161 | } 162 | 163 | public static boolean isDroidXDroid2() { 164 | return (Build.MODEL.trim().equalsIgnoreCase("DROIDX") || Build.MODEL.trim().equalsIgnoreCase("DROID2") || Build.FINGERPRINT.toLowerCase().contains("shadow") || Build.FINGERPRINT.toLowerCase().contains("droid2")); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/ContextUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import android.content.Context; 19 | import android.content.pm.ApplicationInfo; 20 | 21 | public class ContextUtils { 22 | public static int getVersionCode(Context ctx) { 23 | int version = 0; 24 | try { 25 | version = ctx.getPackageManager().getPackageInfo(ctx.getApplicationInfo().packageName, 0).versionCode; 26 | } catch (Exception e) { 27 | Log.e("getVersionInt", e); 28 | } 29 | return version; 30 | } 31 | 32 | public static String getDataDir(Context ctx) { 33 | ApplicationInfo ai = ctx.getApplicationInfo(); 34 | if (ai.dataDir != null) 35 | return fixLastSlash(ai.dataDir); 36 | else 37 | return "/data/data/" + ai.packageName + "/"; 38 | } 39 | 40 | public static String fixLastSlash(String str) { 41 | String res = str == null ? "/" : str.trim() + "/"; 42 | if (res.length() > 2 && res.charAt(res.length() - 2) == '/') 43 | res = res.substring(0, res.length() - 1); 44 | return res; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/Crypto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import java.io.BufferedInputStream; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.ObjectInputStream; 22 | import java.io.UnsupportedEncodingException; 23 | import java.math.BigInteger; 24 | import java.security.MessageDigest; 25 | import java.security.PublicKey; 26 | import java.security.spec.AlgorithmParameterSpec; 27 | 28 | import javax.crypto.Cipher; 29 | import javax.crypto.SecretKey; 30 | import javax.crypto.spec.IvParameterSpec; 31 | import javax.crypto.spec.SecretKeySpec; 32 | 33 | public class Crypto { 34 | private Cipher ecipher; 35 | 36 | public Crypto(String key) { 37 | try { 38 | SecretKeySpec skey = new SecretKeySpec(generateKey(key), "AES"); 39 | setupCrypto(skey); 40 | } catch (Exception e) { 41 | Log.e("Crypto", e); 42 | } 43 | } 44 | 45 | public static String md5(String plain) { 46 | try { 47 | MessageDigest m = MessageDigest.getInstance("MD5"); 48 | m.update(plain.getBytes()); 49 | byte[] digest = m.digest(); 50 | BigInteger bigInt = new BigInteger(1, digest); 51 | String hashtext = bigInt.toString(16); 52 | while (hashtext.length() < 32) { 53 | hashtext = "0" + hashtext; 54 | } 55 | return hashtext; 56 | } catch (Exception e) { 57 | return ""; 58 | } 59 | } 60 | 61 | private static byte[] generateKey(String input) { 62 | try { 63 | byte[] bytesOfMessage = input.getBytes("UTF-8"); 64 | MessageDigest md = MessageDigest.getInstance("SHA256"); 65 | return md.digest(bytesOfMessage); 66 | } catch (Exception e) { 67 | Log.e("generateKey", e); 68 | return null; 69 | } 70 | } 71 | 72 | private void setupCrypto(SecretKey key) { 73 | byte[] iv = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; 74 | AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); 75 | try { 76 | ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 77 | ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); 78 | } catch (Exception e) { 79 | ecipher = null; 80 | Log.e("setupCrypto", e); 81 | } 82 | } 83 | 84 | public String encrypt(String plaintext) { 85 | if (ecipher == null) 86 | return ""; 87 | 88 | try { 89 | byte[] ciphertext = ecipher.doFinal(plaintext.getBytes("UTF-8")); 90 | return Base64.encodeToString(ciphertext, Base64.NO_WRAP); 91 | } catch (Exception e) { 92 | Log.e("encryp", e); 93 | return ""; 94 | } 95 | } 96 | 97 | private PublicKey readKeyFromStream(InputStream keyStream) throws IOException { 98 | ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(keyStream)); 99 | try { 100 | PublicKey pubKey = (PublicKey) oin.readObject(); 101 | return pubKey; 102 | } catch (Exception e) { 103 | Log.e("readKeyFromStream", e); 104 | return null; 105 | } finally { 106 | oin.close(); 107 | } 108 | } 109 | 110 | public String rsaEncrypt(InputStream keyStream, String data) { 111 | try { 112 | return rsaEncrypt(keyStream, data.getBytes("UTF-8")); 113 | } catch (UnsupportedEncodingException e) { 114 | return ""; 115 | } 116 | } 117 | 118 | public String rsaEncrypt(InputStream keyStream, byte[] data) { 119 | try { 120 | PublicKey pubKey = readKeyFromStream(keyStream); 121 | Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 122 | cipher.init(Cipher.ENCRYPT_MODE, pubKey); 123 | byte[] cipherData = cipher.doFinal(data); 124 | return Base64.encodeToString(cipherData, Base64.NO_WRAP); 125 | } catch (Exception e) { 126 | Log.e("rsaEncrypt", e); 127 | return ""; 128 | } 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/Device.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import android.annotation.SuppressLint; 19 | import android.content.Context; 20 | import android.os.Build; 21 | import android.provider.Settings; 22 | import android.telephony.TelephonyManager; 23 | import android.util.DisplayMetrics; 24 | 25 | import java.util.Locale; 26 | 27 | public class Device { 28 | public static String getLocale() { 29 | Locale locale = Locale.getDefault(); 30 | if (locale != null) { 31 | String lo = locale.getLanguage(); 32 | Log.i("getLocale " + lo); 33 | if (lo != null) { 34 | return lo.toLowerCase(); 35 | } 36 | } 37 | return "en"; 38 | } 39 | 40 | public static String getDeviceFeatures(Context ctx) { 41 | return getIdentifiers(ctx) + getSystemFeatures() + getScreenFeatures(ctx); 42 | } 43 | 44 | @SuppressLint("NewApi") 45 | public static String getIdentifiers(Context ctx) { 46 | StringBuilder sb = new StringBuilder(); 47 | sb.append(getPair("serial", Build.SERIAL)); 48 | sb.append(getPair("android_id", Settings.Secure.getString(ctx.getContentResolver(), Settings.Secure.ANDROID_ID))); 49 | TelephonyManager tel = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); 50 | sb.append(getPair("sim_country_iso", tel.getSimCountryIso())); 51 | sb.append(getPair("network_operator_name", tel.getNetworkOperatorName())); 52 | sb.append(getPair("unique_id", Crypto.md5(sb.toString()))); 53 | return sb.toString(); 54 | } 55 | 56 | public static String getSystemFeatures() { 57 | StringBuilder sb = new StringBuilder(); 58 | sb.append(getPair("android_release", Build.VERSION.RELEASE)); 59 | sb.append(getPair("android_sdk_int", "" + Build.VERSION.SDK_INT)); 60 | sb.append(getPair("device_cpu_abi", Build.CPU_ABI)); 61 | sb.append(getPair("device_model", Build.MODEL)); 62 | sb.append(getPair("device_manufacturer", Build.MANUFACTURER)); 63 | sb.append(getPair("device_board", Build.BOARD)); 64 | sb.append(getPair("device_fingerprint", Build.FINGERPRINT)); 65 | sb.append(getPair("device_cpu_feature", CPU.getFeatureString())); 66 | return sb.toString(); 67 | } 68 | 69 | public static String getScreenFeatures(Context ctx) { 70 | StringBuilder sb = new StringBuilder(); 71 | DisplayMetrics disp = ctx.getResources().getDisplayMetrics(); 72 | sb.append(getPair("screen_density", "" + disp.density)); 73 | sb.append(getPair("screen_density_dpi", "" + disp.densityDpi)); 74 | sb.append(getPair("screen_height_pixels", "" + disp.heightPixels)); 75 | sb.append(getPair("screen_width_pixels", "" + disp.widthPixels)); 76 | sb.append(getPair("screen_scaled_density", "" + disp.scaledDensity)); 77 | sb.append(getPair("screen_xdpi", "" + disp.xdpi)); 78 | sb.append(getPair("screen_ydpi", "" + disp.ydpi)); 79 | return sb.toString(); 80 | } 81 | 82 | private static String getPair(String key, String value) { 83 | key = key == null ? "" : key.trim(); 84 | value = value == null ? "" : value.trim(); 85 | return "&" + key + "=" + value; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import android.net.Uri; 19 | import android.text.TextUtils; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | 24 | public class FileUtils { 25 | private static final String FILE_NAME_RESERVED = "|\\?*<\":>+[]/'"; 26 | 27 | public static String getUniqueFileName(String name, String id) { 28 | StringBuilder sb = new StringBuilder(); 29 | for (Character c : name.toCharArray()) { 30 | if (FILE_NAME_RESERVED.indexOf(c) == -1) { 31 | sb.append(c); 32 | } 33 | } 34 | name = sb.toString(); 35 | if (name.length() > 16) { 36 | name = name.substring(0, 16); 37 | } 38 | id = Crypto.md5(id); 39 | name += id; 40 | try { 41 | File f = File.createTempFile(name, null); 42 | if (f.exists()) { 43 | f.delete(); 44 | return name; 45 | } 46 | } catch (IOException e) { 47 | } 48 | return id; 49 | } 50 | 51 | public static String getCanonical(File f) { 52 | if (f == null) 53 | return null; 54 | 55 | try { 56 | return f.getCanonicalPath(); 57 | } catch (IOException e) { 58 | return f.getAbsolutePath(); 59 | } 60 | } 61 | 62 | /** 63 | * Get the path for the file:/// only 64 | * 65 | * @param uri 66 | * @return 67 | */ 68 | public static String getPath(String uri) { 69 | Log.i("FileUtils#getPath(%s)", uri); 70 | if (TextUtils.isEmpty(uri)) 71 | return null; 72 | if (uri.startsWith("file://") && uri.length() > 7) 73 | return Uri.decode(uri.substring(7)); 74 | return Uri.decode(uri); 75 | } 76 | 77 | public static String getName(String uri) { 78 | String path = getPath(uri); 79 | if (path != null) 80 | return new File(path).getName(); 81 | return null; 82 | } 83 | 84 | public static void deleteDir(File f) { 85 | if (f.exists() && f.isDirectory()) { 86 | for (File file : f.listFiles()) { 87 | if (file.isDirectory()) 88 | deleteDir(file); 89 | file.delete(); 90 | } 91 | f.delete(); 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/IOUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import android.database.Cursor; 19 | import android.os.ParcelFileDescriptor; 20 | import android.util.Log; 21 | 22 | import java.io.Closeable; 23 | 24 | public class IOUtils { 25 | 26 | private static final String TAG = "IOUtils"; 27 | 28 | public static void closeSilently(Closeable c) { 29 | if (c == null) 30 | return; 31 | try { 32 | c.close(); 33 | } catch (Throwable t) { 34 | Log.w(TAG, "fail to close", t); 35 | } 36 | } 37 | 38 | public static void closeSilently(ParcelFileDescriptor c) { 39 | if (c == null) 40 | return; 41 | try { 42 | c.close(); 43 | } catch (Throwable t) { 44 | Log.w(TAG, "fail to close", t); 45 | } 46 | } 47 | 48 | public static void closeSilently(Cursor cursor) { 49 | try { 50 | if (cursor != null) cursor.close(); 51 | } catch (Throwable t) { 52 | Log.w(TAG, "fail to close", t); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/Log.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import java.util.MissingFormatArgumentException; 19 | 20 | public class Log { 21 | public static final String TAG = "Vitamio"; 22 | private static final boolean DEBUG = false; 23 | 24 | public static void i(String msg, Object... args) { 25 | // try { 26 | // if (DEBUG) 27 | // android.util.Log.i(TAG, String.format(msg, args)); 28 | // } catch (MissingFormatArgumentException e) { 29 | // android.util.Log.e(TAG, "vitamio.Log", e); 30 | // android.util.Log.i(TAG, msg); 31 | // } 32 | } 33 | 34 | public static void d(String msg, Object... args) { 35 | // try { 36 | // if (DEBUG) 37 | // android.util.Log.d(TAG, String.format(msg, args)); 38 | // } catch (MissingFormatArgumentException e) { 39 | // android.util.Log.e(TAG, "vitamio.Log", e); 40 | // android.util.Log.d(TAG, msg); 41 | // } 42 | } 43 | 44 | public static void e(String msg, Object... args) { 45 | try { 46 | android.util.Log.e(TAG, String.format(msg, args)); 47 | } catch (MissingFormatArgumentException e) { 48 | android.util.Log.e(TAG, "vitamio.Log", e); 49 | android.util.Log.e(TAG, msg); 50 | } 51 | } 52 | 53 | public static void e(String msg, Throwable t) { 54 | android.util.Log.e(TAG, msg, t); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.vov.vitamio.utils; 17 | 18 | import java.util.Arrays; 19 | import java.util.Iterator; 20 | 21 | public class StringUtils { 22 | public static String join(Object[] elements, CharSequence separator) { 23 | return join(Arrays.asList(elements), separator); 24 | } 25 | 26 | public static String join(Iterable elements, CharSequence separator) { 27 | StringBuilder builder = new StringBuilder(); 28 | 29 | if (elements != null) { 30 | Iterator iter = elements.iterator(); 31 | if (iter.hasNext()) { 32 | builder.append(String.valueOf(iter.next())); 33 | while (iter.hasNext()) { 34 | builder.append(separator).append(String.valueOf(iter.next())); 35 | } 36 | } 37 | } 38 | 39 | return builder.toString(); 40 | } 41 | 42 | public static String fixLastSlash(String str) { 43 | String res = str == null ? "/" : str.trim() + "/"; 44 | if (res.length() > 2 && res.charAt(res.length() - 2) == '/') 45 | res = res.substring(0, res.length() - 1); 46 | return res; 47 | } 48 | 49 | public static int convertToInt(String str) throws NumberFormatException { 50 | int s, e; 51 | for (s = 0; s < str.length(); s++) 52 | if (Character.isDigit(str.charAt(s))) 53 | break; 54 | for (e = str.length(); e > 0; e--) 55 | if (Character.isDigit(str.charAt(e - 1))) 56 | break; 57 | if (e > s) { 58 | try { 59 | return Integer.parseInt(str.substring(s, e)); 60 | } catch (NumberFormatException ex) { 61 | Log.e("convertToInt", ex); 62 | throw new NumberFormatException(); 63 | } 64 | } else { 65 | throw new NumberFormatException(); 66 | } 67 | } 68 | 69 | public static String generateTime(long time) { 70 | int totalSeconds = (int) (time / 1000); 71 | int seconds = totalSeconds % 60; 72 | int minutes = (totalSeconds / 60) % 60; 73 | int hours = totalSeconds / 3600; 74 | 75 | return hours > 0 ? String.format("%02d:%02d:%02d", hours, minutes, seconds) : String.format("%02d:%02d", minutes, seconds); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/widget/CenterLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio.widget; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.RemoteViews.RemoteView; 24 | 25 | @RemoteView 26 | public class CenterLayout extends ViewGroup { 27 | private int mPaddingLeft = 0; 28 | private int mPaddingRight = 0; 29 | private int mPaddingTop = 0; 30 | private int mPaddingBottom = 0; 31 | private int mWidth, mHeight; 32 | 33 | public CenterLayout(Context context) { 34 | super(context); 35 | } 36 | 37 | public CenterLayout(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | } 40 | 41 | public CenterLayout(Context context, AttributeSet attrs, int defStyle) { 42 | super(context, attrs, defStyle); 43 | } 44 | 45 | @Override 46 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 47 | int count = getChildCount(); 48 | 49 | int maxHeight = 0; 50 | int maxWidth = 0; 51 | 52 | measureChildren(widthMeasureSpec, heightMeasureSpec); 53 | 54 | for (int i = 0; i < count; i++) { 55 | View child = getChildAt(i); 56 | if (child.getVisibility() != GONE) { 57 | int childRight; 58 | int childBottom; 59 | 60 | CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); 61 | 62 | childRight = lp.x + child.getMeasuredWidth(); 63 | childBottom = lp.y + child.getMeasuredHeight(); 64 | 65 | maxWidth = Math.max(maxWidth, childRight); 66 | maxHeight = Math.max(maxHeight, childBottom); 67 | } 68 | } 69 | 70 | maxWidth += mPaddingLeft + mPaddingRight; 71 | maxHeight += mPaddingTop + mPaddingBottom; 72 | 73 | maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 74 | maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 75 | 76 | setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); 77 | } 78 | 79 | @Override 80 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 81 | int count = getChildCount(); 82 | mWidth = getMeasuredWidth(); 83 | mHeight = getMeasuredHeight(); 84 | for (int i = 0; i < count; i++) { 85 | View child = getChildAt(i); 86 | if (child.getVisibility() != GONE) { 87 | CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); 88 | int childLeft = mPaddingLeft + lp.x; 89 | if (lp.width > 0) 90 | childLeft += (int) ((mWidth - lp.width) / 2.0); 91 | else 92 | childLeft += (int) ((mWidth - child.getMeasuredWidth()) / 2.0); 93 | int childTop = mPaddingTop + lp.y; 94 | if (lp.height > 0) 95 | childTop += (int) ((mHeight - lp.height) / 2.0); 96 | else 97 | childTop += (int) ((mHeight - child.getMeasuredHeight()) / 2.0); 98 | child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); 99 | } 100 | } 101 | } 102 | 103 | @Override 104 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 105 | return p instanceof CenterLayout.LayoutParams; 106 | } 107 | 108 | @Override 109 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 110 | return new LayoutParams(p); 111 | } 112 | 113 | public static class LayoutParams extends ViewGroup.LayoutParams { 114 | public int x; 115 | public int y; 116 | 117 | public LayoutParams(int width, int height, int x, int y) { 118 | super(width, height); 119 | this.x = x; 120 | this.y = y; 121 | } 122 | 123 | public LayoutParams(ViewGroup.LayoutParams source) { 124 | super(source); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /vitamio/src/io/vov/vitamio/widget/OutlineTextView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 YIXIA.COM 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.vov.vitamio.widget; 18 | 19 | import android.content.Context; 20 | import android.graphics.Canvas; 21 | import android.graphics.Paint; 22 | import android.graphics.Typeface; 23 | import android.text.Layout; 24 | import android.text.StaticLayout; 25 | import android.text.TextPaint; 26 | import android.util.AttributeSet; 27 | import android.widget.TextView; 28 | 29 | /** 30 | * Display text with border, use the same XML attrs as 31 | * {@link android.widget.TextView}, except that {@link OutlineTextView} will 32 | * transform the shadow to border 33 | */ 34 | public class OutlineTextView extends TextView { 35 | private TextPaint mTextPaint; 36 | private TextPaint mTextPaintOutline; 37 | private String mText = ""; 38 | private int mAscent = 0; 39 | private float mBorderSize; 40 | private int mBorderColor; 41 | private int mColor; 42 | private float mSpacingMult = 1.0f; 43 | private float mSpacingAdd = 0; 44 | private boolean mIncludePad = true; 45 | 46 | public OutlineTextView(Context context) { 47 | super(context); 48 | initPaint(); 49 | } 50 | 51 | public OutlineTextView(Context context, AttributeSet attrs) { 52 | super(context, attrs); 53 | initPaint(); 54 | } 55 | 56 | public OutlineTextView(Context context, AttributeSet attrs, int defStyle) { 57 | super(context, attrs, defStyle); 58 | initPaint(); 59 | } 60 | 61 | private void initPaint() { 62 | mTextPaint = new TextPaint(); 63 | mTextPaint.setAntiAlias(true); 64 | mTextPaint.setTextSize(getTextSize()); 65 | mTextPaint.setColor(mColor); 66 | mTextPaint.setStyle(Paint.Style.FILL); 67 | mTextPaint.setTypeface(getTypeface()); 68 | 69 | mTextPaintOutline = new TextPaint(); 70 | mTextPaintOutline.setAntiAlias(true); 71 | mTextPaintOutline.setTextSize(getTextSize()); 72 | mTextPaintOutline.setColor(mBorderColor); 73 | mTextPaintOutline.setStyle(Paint.Style.STROKE); 74 | mTextPaintOutline.setTypeface(getTypeface()); 75 | mTextPaintOutline.setStrokeWidth(mBorderSize); 76 | } 77 | 78 | public void setText(String text) { 79 | super.setText(text); 80 | mText = text.toString(); 81 | requestLayout(); 82 | invalidate(); 83 | } 84 | 85 | public void setTextSize(float size) { 86 | super.setTextSize(size); 87 | requestLayout(); 88 | invalidate(); 89 | initPaint(); 90 | } 91 | 92 | public void setTextColor(int color) { 93 | super.setTextColor(color); 94 | mColor = color; 95 | invalidate(); 96 | initPaint(); 97 | } 98 | 99 | public void setShadowLayer(float radius, float dx, float dy, int color) { 100 | super.setShadowLayer(radius, dx, dy, color); 101 | mBorderSize = radius; 102 | mBorderColor = color; 103 | requestLayout(); 104 | invalidate(); 105 | initPaint(); 106 | } 107 | 108 | public void setTypeface(Typeface tf, int style) { 109 | super.setTypeface(tf, style); 110 | requestLayout(); 111 | invalidate(); 112 | initPaint(); 113 | } 114 | 115 | public void setTypeface(Typeface tf) { 116 | super.setTypeface(tf); 117 | requestLayout(); 118 | invalidate(); 119 | initPaint(); 120 | } 121 | 122 | @Override 123 | protected void onDraw(Canvas canvas) { 124 | Layout layout = new StaticLayout(getText(), mTextPaintOutline, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); 125 | layout.draw(canvas); 126 | layout = new StaticLayout(getText(), mTextPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); 127 | layout.draw(canvas); 128 | } 129 | 130 | @Override 131 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 132 | Layout layout = new StaticLayout(getText(), mTextPaintOutline, measureWidth(widthMeasureSpec), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); 133 | int ex = (int) (mBorderSize * 2 + 1); 134 | setMeasuredDimension(measureWidth(widthMeasureSpec) + ex, measureHeight(heightMeasureSpec) * layout.getLineCount() + ex); 135 | } 136 | 137 | private int measureWidth(int measureSpec) { 138 | int result = 0; 139 | int specMode = MeasureSpec.getMode(measureSpec); 140 | int specSize = MeasureSpec.getSize(measureSpec); 141 | 142 | if (specMode == MeasureSpec.EXACTLY) { 143 | result = specSize; 144 | } else { 145 | result = (int) mTextPaintOutline.measureText(mText) + getPaddingLeft() + getPaddingRight(); 146 | if (specMode == MeasureSpec.AT_MOST) { 147 | result = Math.min(result, specSize); 148 | } 149 | } 150 | 151 | return result; 152 | } 153 | 154 | private int measureHeight(int measureSpec) { 155 | int result = 0; 156 | int specMode = MeasureSpec.getMode(measureSpec); 157 | int specSize = MeasureSpec.getSize(measureSpec); 158 | 159 | mAscent = (int) mTextPaintOutline.ascent(); 160 | if (specMode == MeasureSpec.EXACTLY) { 161 | result = specSize; 162 | } else { 163 | result = (int) (-mAscent + mTextPaintOutline.descent()) + getPaddingTop() + getPaddingBottom(); 164 | if (specMode == MeasureSpec.AT_MOST) { 165 | result = Math.min(result, specSize); 166 | } 167 | } 168 | return result; 169 | } 170 | } -------------------------------------------------------------------------------- /vitamio/vitamio.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | --------------------------------------------------------------------------------