├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── android-support-v4.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── mediaserver │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── mediaserver │ │ │ ├── DeviceInfo.java │ │ │ ├── DeviceUpdateBrocastFactory.java │ │ │ ├── DeviceUpdateBrocastReceiver.java │ │ │ ├── MainActivity.java │ │ │ ├── ServerApplication.java │ │ │ ├── server │ │ │ ├── DMSService.java │ │ │ ├── center │ │ │ │ ├── DMSWorkThread.java │ │ │ │ ├── IBaseEngine.java │ │ │ │ ├── LocalConfigSharePreference.java │ │ │ │ ├── MediaServerProxy.java │ │ │ │ └── MediaStoreCenter.java │ │ │ ├── jni │ │ │ │ └── DMSJniInterface.java │ │ │ └── media │ │ │ │ ├── IMediaScanListener.java │ │ │ │ └── MediaScannerCenter.java │ │ │ └── util │ │ │ ├── CommonLog.java │ │ │ ├── CommonUtil.java │ │ │ ├── DlnaUtils.java │ │ │ ├── FileHelper.java │ │ │ └── LogFactory.java │ ├── jniLibs │ │ └── armeabi │ │ │ └── libgit-platinum.so │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_launcher.png │ │ └── main_bg.png │ │ ├── drawable-ldpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable │ │ ├── button_normal.9.png │ │ ├── button_pressed.9.png │ │ ├── input_disabled.9.png │ │ ├── input_normal.9.png │ │ ├── input_pressed.9.png │ │ ├── logo.png │ │ ├── selector_btn.xml │ │ └── selector_edit.xml │ │ ├── layout │ │ └── activity_main.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── github │ └── mediaserver │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | MediaServer -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | a MediaServer run in Android Platform 2 | =========== 3 | MediaServer is a DLNA device(DMS) that can be browsed by control
It uses the framework of Platinum 4 | 5 | Example screenshot below: 6 | 7 | ![github](http://img.my.csdn.net/uploads/201308/09/1376054213_2513.png "github") 8 | 9 | 10 | 11 | Code fragment 12 | -------------------- 13 | public class DMSService extends Service implements IBaseEngine{ 14 | 15 | private static final CommonLog log = LogFactory.createLog(); 16 | 17 | public static final String START_SERVER_ENGINE = "com.geniusgithub.start.dmsengine"; 18 | public static final String RESTART_SERVER_ENGINE = "com.geniusgithub.restart.dmsengine"; 19 | 20 | private DMSWorkThread mWorkThread; 21 | 22 | private Handler mHandler; 23 | private static final int START_ENGINE_MSG_ID = 0x0001; 24 | private static final int RESTART_ENGINE_MSG_ID = 0x0002; 25 | 26 | private static final int DELAY_TIME = 1000; 27 | 28 | private MediaStoreCenter mMediaStoreCenter; 29 | 30 | @Override 31 | public IBinder onBind(Intent intent) { 32 | return null; 33 | } 34 | 35 | @Override 36 | public void onCreate() { 37 | super.onCreate(); 38 | initService(); 39 | log.e("MediaServerService onCreate"); 40 | } 41 | 42 | @Override 43 | public void onDestroy() { 44 | unInitService(); 45 | log.e("MediaServerService onDestroy"); 46 | super.onDestroy(); 47 | 48 | } 49 | 50 | @Override 51 | public int onStartCommand(Intent intent, int flags, int startId) { 52 | 53 | if (intent != null){ 54 | String actionString = intent.getAction(); 55 | if (actionString != null){ 56 | if (actionString.equalsIgnoreCase(START_SERVER_ENGINE)){ 57 | delayToSendStartMsg(); 58 | }else if (actionString.equalsIgnoreCase(RESTART_SERVER_ENGINE)){ 59 | delayToSendRestartMsg(); 60 | } 61 | } 62 | } 63 | 64 | return super.onStartCommand(intent, flags, startId); 65 | 66 | } 67 | 68 | 69 | private void initService(){ 70 | 71 | mWorkThread = new DMSWorkThread(this); 72 | 73 | mHandler = new Handler(){ 74 | @Override 75 | public void handleMessage(Message msg) { 76 | switch(msg.what){ 77 | case START_ENGINE_MSG_ID: 78 | startEngine(); 79 | break; 80 | case RESTART_ENGINE_MSG_ID: 81 | restartEngine(); 82 | break; 83 | } 84 | } 85 | 86 | }; 87 | 88 | mMediaStoreCenter = MediaStoreCenter.getInstance(); 89 | mMediaStoreCenter.clearWebFolder(); 90 | mMediaStoreCenter.createWebFolder(); 91 | mMediaStoreCenter.doScanMedia(); 92 | } 93 | 94 | 95 | private void unInitService(){ 96 | stopEngine(); 97 | removeStartMsg(); 98 | removeRestartMsg(); 99 | mMediaStoreCenter.clearAllData(); 100 | } 101 | 102 | private void delayToSendStartMsg(){ 103 | removeStartMsg(); 104 | mHandler.sendEmptyMessageDelayed(START_ENGINE_MSG_ID, DELAY_TIME); 105 | } 106 | 107 | private void delayToSendRestartMsg(){ 108 | removeStartMsg(); 109 | removeRestartMsg(); 110 | mHandler.sendEmptyMessageDelayed(RESTART_ENGINE_MSG_ID, DELAY_TIME); 111 | } 112 | 113 | private void removeStartMsg(){ 114 | mHandler.removeMessages(START_ENGINE_MSG_ID); 115 | } 116 | 117 | private void removeRestartMsg(){ 118 | mHandler.removeMessages(RESTART_ENGINE_MSG_ID); 119 | } 120 | 121 | 122 | @Override 123 | public boolean startEngine() { 124 | awakeWorkThread(); 125 | return true; 126 | } 127 | 128 | @Override 129 | public boolean stopEngine() { 130 | mWorkThread.setParam("", "", ""); 131 | exitWorkThread(); 132 | return true; 133 | } 134 | 135 | @Override 136 | public boolean restartEngine() { 137 | String friendName = DlnaUtils.getDevName(this); 138 | String uuid = DlnaUtils.creat12BitUUID(this); 139 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid); 140 | if (mWorkThread.isAlive()){ 141 | mWorkThread.restartEngine(); 142 | }else{ 143 | mWorkThread.start(); 144 | } 145 | return true; 146 | } 147 | 148 | private void awakeWorkThread(){ 149 | String friendName = DlnaUtils.getDevName(this); 150 | String uuid = DlnaUtils.creat12BitUUID(this); 151 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid); 152 | 153 | 154 | if (mWorkThread.isAlive()){ 155 | mWorkThread.awakeThread(); 156 | }else{ 157 | mWorkThread.start(); 158 | } 159 | } 160 | 161 | private void exitWorkThread(){ 162 | if (mWorkThread != null && mWorkThread.isAlive()){ 163 | mWorkThread.exit(); 164 | long time1 = System.currentTimeMillis(); 165 | while(mWorkThread.isAlive()){ 166 | try { 167 | Thread.sleep(100); 168 | } catch (InterruptedException e) { 169 | e.printStackTrace(); 170 | } 171 | } 172 | long time2 = System.currentTimeMillis(); 173 | log.e("exitWorkThread cost time:" + (time2 - time1)); 174 | mWorkThread = null; 175 | } 176 | } 177 | 178 | 179 | } 180 | 181 | 182 | 183 | public class DMSWorkThread extends Thread implements IBaseEngine{ 184 | 185 | 186 | private static final CommonLog log = LogFactory.createLog(); 187 | 188 | private static final int CHECK_INTERVAL = 30 * 1000; 189 | 190 | private Context mContext = null; 191 | private boolean mStartSuccess = false; 192 | private boolean mExitFlag = false; 193 | 194 | private String mRootdir = ""; 195 | private String mFriendName = ""; 196 | private String mUUID = ""; 197 | private ServerApplication mApplication; 198 | 199 | public DMSWorkThread(Context context){ 200 | mContext = context; 201 | mApplication = ServerApplication.getInstance(); 202 | } 203 | 204 | public void setFlag(boolean flag){ 205 | mStartSuccess = flag; 206 | } 207 | 208 | public void setParam(String rootDir, String friendName, String uuid){ 209 | mRootdir = rootDir; 210 | mFriendName = friendName; 211 | mUUID = uuid; 212 | mApplication.updateDevInfo(mRootdir, mFriendName, mUUID); 213 | } 214 | 215 | public void awakeThread(){ 216 | synchronized (this) { 217 | notifyAll(); 218 | } 219 | } 220 | 221 | public void exit(){ 222 | mExitFlag = true; 223 | awakeThread(); 224 | } 225 | 226 | @Override 227 | public void run() { 228 | 229 | log.e("DMSWorkThread run..."); 230 | 231 | while(true) 232 | { 233 | if (mExitFlag){ 234 | stopEngine(); 235 | break; 236 | } 237 | refreshNotify(); 238 | synchronized(this) 239 | { 240 | try 241 | { 242 | wait(CHECK_INTERVAL); 243 | } 244 | catch(Exception e) 245 | { 246 | e.printStackTrace(); 247 | } 248 | } 249 | if (mExitFlag){ 250 | stopEngine(); 251 | break; 252 | } 253 | } 254 | 255 | log.e("DMSWorkThread over..."); 256 | 257 | } 258 | 259 | public void refreshNotify(){ 260 | if (!CommonUtil.checkNetworkState(mContext)){ 261 | return ; 262 | } 263 | 264 | if (!mStartSuccess){ 265 | stopEngine(); 266 | try { 267 | Thread.sleep(200); 268 | } catch (InterruptedException e) { 269 | e.printStackTrace(); 270 | } 271 | boolean ret = startEngine(); 272 | if (ret){ 273 | mStartSuccess = true; 274 | } 275 | } 276 | 277 | } 278 | 279 | @Override 280 | public boolean startEngine() { 281 | if (mFriendName.length() == 0){ 282 | return false; 283 | } 284 | 285 | int ret = DMSJniInterface.startServer(mRootdir, mFriendName, mUUID); 286 | 287 | boolean result = (ret == 0 ? true : false); 288 | mApplication.setDevStatus(result); 289 | return result; 290 | } 291 | 292 | @Override 293 | public boolean stopEngine() { 294 | DMSJniInterface.stopServer(); 295 | mApplication.setDevStatus(false); 296 | return true; 297 | } 298 | 299 | @Override 300 | public boolean restartEngine() { 301 | setFlag(false); 302 | awakeThread(); 303 | return true; 304 | } 305 | 306 | } 307 | 308 | 309 | 310 | Run requirements 311 | ------------------------------ 312 | Android OS 2.3x and up
313 | Tested with: Samsung, HTC, HuaWei Phone and so on... 314 | 315 | 316 | Contributing 317 | ------------------------------ 318 | Feel free to drop me pull requests. If you plan to implement something more than a few lines, then open the pull request early so that there aren't any nasty surprises later. 319 | If you want to add something that will require some for of persistence incl. persistent configuration or API keys, etc., then open a pull request/issue especially early! 320 | 321 | 322 | ### Links 323 | csdn blog : [http://blog.csdn.net/geniuseoe2012](http://blog.csdn.net/geniuseoe2012)
324 | cnblog : [http://www.cnblogs.com/lance2016](http://www.cnblogs.com/lance2016/p/5204315.html)
325 | dlna doc: [DLNA Document](http://download.csdn.net/detail/geniuseoe2012/4969961)
326 | Platinum SDK : [Platinum](http://sourceforge.net/projects/platinum/)
327 | 328 | ### Development 329 | If you think this article useful Nepal , please pay attention to me
330 | Your support is my motivation, I will continue to strive to do better 331 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.github.mediaserver" 9 | minSdkVersion 19 10 | targetSdkVersion 22 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(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | } 26 | -------------------------------------------------------------------------------- /app/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/libs/android-support-v4.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:\sofeware\android-sdk-L/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/com/github/mediaserver/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 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 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/DeviceInfo.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 2 | 3 | public class DeviceInfo { 4 | 5 | public String dev_name; 6 | public String uuid; 7 | public String rootDir; 8 | public boolean status; 9 | 10 | public DeviceInfo(){ 11 | rootDir = ""; 12 | dev_name = ""; 13 | uuid = ""; 14 | status = false; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/DeviceUpdateBrocastFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.IntentFilter; 6 | 7 | 8 | public class DeviceUpdateBrocastFactory { 9 | 10 | public static final String PARAM_DEV_UPDATE="com.geniusgithub.dms.PARAM_DEV_UPDATE"; 11 | 12 | public static interface IDevUpdateListener { 13 | public void onUpdate(); 14 | } 15 | 16 | 17 | private DeviceUpdateBrocastReceiver mReceiver; 18 | private Context mContext; 19 | 20 | public DeviceUpdateBrocastFactory(Context context){ 21 | mContext = context; 22 | } 23 | 24 | 25 | public void register(IDevUpdateListener listener){ 26 | if (mReceiver == null){ 27 | mReceiver = new DeviceUpdateBrocastReceiver(); 28 | mReceiver.setListener(listener); 29 | mContext.registerReceiver(mReceiver, new IntentFilter(PARAM_DEV_UPDATE)); 30 | } 31 | } 32 | 33 | public void unregister() 34 | { 35 | if (mReceiver != null){ 36 | mContext.unregisterReceiver(mReceiver); 37 | mReceiver = null; 38 | } 39 | } 40 | 41 | public static void sendDevUpdateBrocast(Context context){ 42 | Intent intent = new Intent(); 43 | intent.setAction(PARAM_DEV_UPDATE); 44 | context.sendBroadcast(intent); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/DeviceUpdateBrocastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.github.mediaserver.util.CommonLog; 8 | import com.github.mediaserver.util.LogFactory; 9 | 10 | 11 | 12 | public class DeviceUpdateBrocastReceiver extends BroadcastReceiver{ 13 | 14 | private static final CommonLog log = LogFactory.createLog(); 15 | private DeviceUpdateBrocastFactory.IDevUpdateListener mListener; 16 | 17 | public void setListener(DeviceUpdateBrocastFactory.IDevUpdateListener listener){ 18 | mListener = listener; 19 | } 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | String action = intent.getAction(); 23 | if (action == null){ 24 | return ; 25 | } 26 | 27 | if (DeviceUpdateBrocastFactory.PARAM_DEV_UPDATE.equalsIgnoreCase(action)){ 28 | if (mListener != null){ 29 | mListener.onUpdate(); 30 | } 31 | } 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.view.View.OnClickListener; 7 | import android.widget.Button; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | 11 | import com.github.mediaserver.server.center.MediaServerProxy; 12 | import com.github.mediaserver.util.CommonLog; 13 | import com.github.mediaserver.util.DlnaUtils; 14 | import com.github.mediaserver.util.LogFactory; 15 | 16 | 17 | /** 18 | * @author lance 19 | * @csdn http://blog.csdn.net/geniuseoe2012 20 | * @github https://github.com/geniusgithub 21 | */ 22 | public class MainActivity extends Activity implements OnClickListener, DeviceUpdateBrocastFactory.IDevUpdateListener{ 23 | 24 | private static final CommonLog log = LogFactory.createLog(); 25 | 26 | private Button mBtnStart; 27 | private Button mBtnReset; 28 | private Button mBtnStop; 29 | 30 | private Button mBtnEditName; 31 | private EditText mETName; 32 | private TextView mTVDevInfo; 33 | 34 | 35 | private MediaServerProxy mServerProxy; 36 | private ServerApplication mApplication; 37 | private DeviceUpdateBrocastFactory mBrocastFactory; 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | setContentView(R.layout.activity_main); 43 | 44 | setupView(); 45 | initData(); 46 | } 47 | 48 | 49 | 50 | 51 | @Override 52 | protected void onDestroy() { 53 | unInitData(); 54 | super.onDestroy(); 55 | } 56 | 57 | 58 | 59 | 60 | private void setupView(){ 61 | mBtnStart = (Button) findViewById(R.id.btn_init); 62 | mBtnReset = (Button) findViewById(R.id.btn_reset); 63 | mBtnStop = (Button) findViewById(R.id.btn_exit); 64 | mBtnEditName = (Button) findViewById(R.id.bt_dev_name); 65 | mBtnStart.setOnClickListener(this); 66 | mBtnReset.setOnClickListener(this); 67 | mBtnStop.setOnClickListener(this); 68 | mBtnEditName.setOnClickListener(this); 69 | 70 | mTVDevInfo = (TextView) findViewById(R.id.tv_dev_info); 71 | mETName = (EditText) findViewById(R.id.et_dev_name); 72 | 73 | } 74 | 75 | private void initData(){ 76 | mApplication = ServerApplication.getInstance(); 77 | mServerProxy = MediaServerProxy.getInstance(); 78 | mBrocastFactory = new DeviceUpdateBrocastFactory(this); 79 | 80 | String dev_name = DlnaUtils.getDevName(this); 81 | mETName.setText(dev_name); 82 | mETName.setEnabled(false); 83 | 84 | updateDevInfo(mApplication.getDevInfo()); 85 | mBrocastFactory.register(this); 86 | } 87 | 88 | private void unInitData(){ 89 | mBrocastFactory.unregister(); 90 | } 91 | 92 | private void updateDevInfo(DeviceInfo object){ 93 | String status = object.status ? "open" : "close"; 94 | String text = "status: " + status + "\n" + 95 | "friend name: " + object.dev_name + "\n" + 96 | "uuid: " + object.uuid; 97 | mTVDevInfo.setText(text); 98 | } 99 | 100 | @Override 101 | public void onClick(View v) { 102 | switch(v.getId()){ 103 | case R.id.btn_init: 104 | start(); 105 | break; 106 | case R.id.btn_reset: 107 | reset(); 108 | break; 109 | case R.id.btn_exit: 110 | stop(); 111 | finish(); 112 | break; 113 | case R.id.bt_dev_name: 114 | change(); 115 | break; 116 | } 117 | } 118 | 119 | 120 | private void start(){ 121 | mServerProxy.startEngine(); 122 | } 123 | 124 | private void reset(){ 125 | mServerProxy.restartEngine(); 126 | } 127 | 128 | private void stop(){ 129 | mServerProxy.stopEngine(); 130 | } 131 | 132 | private void change(){ 133 | if (mETName.isEnabled()){ 134 | mETName.setEnabled(false); 135 | DlnaUtils.setDevName(this, mETName.getText().toString()); 136 | }else{ 137 | mETName.setEnabled(true); 138 | } 139 | } 140 | 141 | 142 | 143 | @Override 144 | public void onUpdate() { 145 | updateDevInfo(mApplication.getDevInfo()); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/ServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver; 2 | 3 | import com.github.mediaserver.util.CommonLog; 4 | import com.github.mediaserver.util.LogFactory; 5 | 6 | import android.app.Application; 7 | 8 | 9 | 10 | public class ServerApplication extends Application{ 11 | 12 | private static final CommonLog log = LogFactory.createLog(); 13 | 14 | private static ServerApplication mInstance; 15 | 16 | private DeviceInfo mDeviceInfo; 17 | 18 | 19 | public synchronized static ServerApplication getInstance(){ 20 | return mInstance; 21 | } 22 | @Override 23 | public void onCreate() { 24 | super.onCreate(); 25 | log.e("ServerApplication onCreate"); 26 | 27 | mInstance = this; 28 | mDeviceInfo = new DeviceInfo(); 29 | } 30 | 31 | public void updateDevInfo(String rootDir, String name, String uuid){ 32 | mDeviceInfo.rootDir = rootDir; 33 | mDeviceInfo.dev_name = name; 34 | mDeviceInfo.uuid = uuid; 35 | } 36 | 37 | public void setDevStatus(boolean flag){ 38 | mDeviceInfo.status = flag; 39 | DeviceUpdateBrocastFactory.sendDevUpdateBrocast(this); 40 | } 41 | 42 | public DeviceInfo getDevInfo(){ 43 | return mDeviceInfo; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/DMSService.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server; 2 | 3 | 4 | 5 | 6 | import android.app.Service; 7 | import android.content.Intent; 8 | import android.net.wifi.WifiManager.MulticastLock; 9 | import android.os.Handler; 10 | import android.os.IBinder; 11 | import android.os.Message; 12 | 13 | import com.github.mediaserver.server.center.DMSWorkThread; 14 | import com.github.mediaserver.server.center.IBaseEngine; 15 | import com.github.mediaserver.server.center.MediaStoreCenter; 16 | import com.github.mediaserver.util.CommonLog; 17 | import com.github.mediaserver.util.CommonUtil; 18 | import com.github.mediaserver.util.DlnaUtils; 19 | import com.github.mediaserver.util.LogFactory; 20 | 21 | public class DMSService extends Service implements IBaseEngine{ 22 | 23 | private static final CommonLog log = LogFactory.createLog(); 24 | 25 | public static final String START_SERVER_ENGINE = "com.geniusgithub.start.dmsengine"; 26 | public static final String RESTART_SERVER_ENGINE = "com.geniusgithub.restart.dmsengine"; 27 | 28 | private DMSWorkThread mWorkThread; 29 | 30 | private Handler mHandler; 31 | private static final int START_ENGINE_MSG_ID = 0x0001; 32 | private static final int RESTART_ENGINE_MSG_ID = 0x0002; 33 | 34 | private static final int DELAY_TIME = 1000; 35 | 36 | private MediaStoreCenter mMediaStoreCenter; 37 | private MulticastLock mMulticastLock; 38 | @Override 39 | public IBinder onBind(Intent intent) { 40 | return null; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | initService(); 47 | log.e("MediaServerService onCreate"); 48 | } 49 | 50 | @Override 51 | public void onDestroy() { 52 | unInitService(); 53 | log.e("MediaServerService onDestroy"); 54 | super.onDestroy(); 55 | 56 | } 57 | 58 | @Override 59 | public int onStartCommand(Intent intent, int flags, int startId) { 60 | 61 | if (intent != null){ 62 | String actionString = intent.getAction(); 63 | if (actionString != null){ 64 | if (actionString.equalsIgnoreCase(START_SERVER_ENGINE)){ 65 | delayToSendStartMsg(); 66 | }else if (actionString.equalsIgnoreCase(RESTART_SERVER_ENGINE)){ 67 | delayToSendRestartMsg(); 68 | } 69 | } 70 | } 71 | 72 | return super.onStartCommand(intent, flags, startId); 73 | 74 | } 75 | 76 | 77 | private void initService(){ 78 | 79 | mWorkThread = new DMSWorkThread(this); 80 | 81 | mHandler = new Handler(){ 82 | @Override 83 | public void handleMessage(Message msg) { 84 | switch(msg.what){ 85 | case START_ENGINE_MSG_ID: 86 | startEngine(); 87 | break; 88 | case RESTART_ENGINE_MSG_ID: 89 | restartEngine(); 90 | break; 91 | } 92 | } 93 | 94 | }; 95 | 96 | mMediaStoreCenter = MediaStoreCenter.getInstance(); 97 | mMediaStoreCenter.clearWebFolder(); 98 | mMediaStoreCenter.createWebFolder(); 99 | mMediaStoreCenter.doScanMedia(); 100 | 101 | mMulticastLock = CommonUtil.openWifiBrocast(this); 102 | log.e("openWifiBrocast = " + mMulticastLock != null ? true : false); 103 | } 104 | 105 | 106 | private void unInitService(){ 107 | stopEngine(); 108 | removeStartMsg(); 109 | removeRestartMsg(); 110 | mMediaStoreCenter.clearAllData(); 111 | 112 | if (mMulticastLock != null){ 113 | mMulticastLock.release(); 114 | mMulticastLock = null; 115 | log.e("closeWifiBrocast"); 116 | } 117 | } 118 | 119 | private void delayToSendStartMsg(){ 120 | removeStartMsg(); 121 | mHandler.sendEmptyMessageDelayed(START_ENGINE_MSG_ID, DELAY_TIME); 122 | } 123 | 124 | private void delayToSendRestartMsg(){ 125 | removeStartMsg(); 126 | removeRestartMsg(); 127 | mHandler.sendEmptyMessageDelayed(RESTART_ENGINE_MSG_ID, DELAY_TIME); 128 | } 129 | 130 | private void removeStartMsg(){ 131 | mHandler.removeMessages(START_ENGINE_MSG_ID); 132 | } 133 | 134 | private void removeRestartMsg(){ 135 | mHandler.removeMessages(RESTART_ENGINE_MSG_ID); 136 | } 137 | 138 | 139 | @Override 140 | public boolean startEngine() { 141 | awakeWorkThread(); 142 | return true; 143 | } 144 | 145 | @Override 146 | public boolean stopEngine() { 147 | mWorkThread.setParam("", "", ""); 148 | exitWorkThread(); 149 | return true; 150 | } 151 | 152 | @Override 153 | public boolean restartEngine() { 154 | String friendName = DlnaUtils.getDevName(this); 155 | String uuid = DlnaUtils.creat12BitUUID(this); 156 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid); 157 | if (mWorkThread.isAlive()){ 158 | mWorkThread.restartEngine(); 159 | }else{ 160 | mWorkThread.start(); 161 | } 162 | return true; 163 | } 164 | 165 | private void awakeWorkThread(){ 166 | String friendName = DlnaUtils.getDevName(this); 167 | String uuid = DlnaUtils.creat12BitUUID(this); 168 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid); 169 | 170 | 171 | if (mWorkThread.isAlive()){ 172 | mWorkThread.awakeThread(); 173 | }else{ 174 | mWorkThread.start(); 175 | } 176 | } 177 | 178 | private void exitWorkThread(){ 179 | if (mWorkThread != null && mWorkThread.isAlive()){ 180 | mWorkThread.exit(); 181 | long time1 = System.currentTimeMillis(); 182 | while(mWorkThread.isAlive()){ 183 | try { 184 | Thread.sleep(100); 185 | } catch (InterruptedException e) { 186 | e.printStackTrace(); 187 | } 188 | } 189 | long time2 = System.currentTimeMillis(); 190 | log.e("exitWorkThread cost time:" + (time2 - time1)); 191 | mWorkThread = null; 192 | } 193 | } 194 | 195 | 196 | } 197 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/center/DMSWorkThread.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.center; 2 | 3 | import com.github.mediaserver.ServerApplication; 4 | import com.github.mediaserver.server.jni.DMSJniInterface; 5 | import com.github.mediaserver.util.CommonLog; 6 | import com.github.mediaserver.util.CommonUtil; 7 | import com.github.mediaserver.util.LogFactory; 8 | import android.content.Context; 9 | 10 | 11 | public class DMSWorkThread extends Thread implements IBaseEngine{ 12 | 13 | 14 | private static final CommonLog log = LogFactory.createLog(); 15 | 16 | private static final int CHECK_INTERVAL = 30 * 1000; 17 | 18 | private Context mContext = null; 19 | private boolean mStartSuccess = false; 20 | private boolean mExitFlag = false; 21 | 22 | private String mRootdir = ""; 23 | private String mFriendName = ""; 24 | private String mUUID = ""; 25 | private ServerApplication mApplication; 26 | 27 | public DMSWorkThread(Context context){ 28 | mContext = context; 29 | mApplication = ServerApplication.getInstance(); 30 | } 31 | 32 | public void setFlag(boolean flag){ 33 | mStartSuccess = flag; 34 | } 35 | 36 | public void setParam(String rootDir, String friendName, String uuid){ 37 | mRootdir = rootDir; 38 | mFriendName = friendName; 39 | mUUID = uuid; 40 | mApplication.updateDevInfo(mRootdir, mFriendName, mUUID); 41 | } 42 | 43 | public void awakeThread(){ 44 | synchronized (this) { 45 | notifyAll(); 46 | } 47 | } 48 | 49 | public void exit(){ 50 | mExitFlag = true; 51 | awakeThread(); 52 | } 53 | 54 | @Override 55 | public void run() { 56 | 57 | log.e("DMSWorkThread run..."); 58 | 59 | while(true) 60 | { 61 | if (mExitFlag){ 62 | stopEngine(); 63 | break; 64 | } 65 | refreshNotify(); 66 | synchronized(this) 67 | { 68 | try 69 | { 70 | wait(CHECK_INTERVAL); 71 | } 72 | catch(Exception e) 73 | { 74 | e.printStackTrace(); 75 | } 76 | } 77 | if (mExitFlag){ 78 | stopEngine(); 79 | break; 80 | } 81 | } 82 | 83 | log.e("DMSWorkThread over..."); 84 | 85 | } 86 | 87 | public void refreshNotify(){ 88 | if (!CommonUtil.checkNetworkState(mContext)){ 89 | return ; 90 | } 91 | 92 | if (!mStartSuccess){ 93 | stopEngine(); 94 | try { 95 | Thread.sleep(200); 96 | } catch (InterruptedException e) { 97 | e.printStackTrace(); 98 | } 99 | boolean ret = startEngine(); 100 | if (ret){ 101 | mStartSuccess = true; 102 | } 103 | } 104 | 105 | } 106 | 107 | @Override 108 | public boolean startEngine() { 109 | if (mFriendName.length() == 0){ 110 | return false; 111 | } 112 | 113 | int ret = DMSJniInterface.startServer(mRootdir, mFriendName, mUUID); 114 | 115 | boolean result = (ret == 0 ? true : false); 116 | mApplication.setDevStatus(result); 117 | return result; 118 | } 119 | 120 | @Override 121 | public boolean stopEngine() { 122 | DMSJniInterface.stopServer(); 123 | mApplication.setDevStatus(false); 124 | return true; 125 | } 126 | 127 | @Override 128 | public boolean restartEngine() { 129 | setFlag(false); 130 | awakeThread(); 131 | return true; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/center/IBaseEngine.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.center; 2 | 3 | public interface IBaseEngine { 4 | 5 | public boolean startEngine(); 6 | public boolean stopEngine(); 7 | public boolean restartEngine(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/center/LocalConfigSharePreference.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.center; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.content.SharedPreferences.Editor; 6 | 7 | public class LocalConfigSharePreference { 8 | 9 | public static final String preference_name = "LocalConfigSharePreference"; 10 | public static final String dev_name = "dev_name"; 11 | 12 | public static boolean commintDevName(Context context, String devName){ 13 | 14 | SharedPreferences sharedPreferences = context.getSharedPreferences(preference_name, 0); 15 | Editor editor = sharedPreferences.edit(); 16 | editor.putString(dev_name, devName); 17 | editor.commit(); 18 | return true; 19 | } 20 | 21 | public static String getDevName(Context context){ 22 | SharedPreferences sharedPreferences = context.getSharedPreferences(preference_name, 0); 23 | String value = sharedPreferences.getString(dev_name, "geniusgithub"); 24 | return value; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/center/MediaServerProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.center; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.github.mediaserver.ServerApplication; 8 | import com.github.mediaserver.server.DMSService; 9 | import com.github.mediaserver.util.CommonLog; 10 | import com.github.mediaserver.util.LogFactory; 11 | 12 | public class MediaServerProxy implements IBaseEngine{ 13 | 14 | private static final CommonLog log = LogFactory.createLog(); 15 | 16 | private static MediaServerProxy mInstance; 17 | private Context mContext; 18 | 19 | private MediaServerProxy(Context context) { 20 | mContext = context; 21 | } 22 | 23 | public static synchronized MediaServerProxy getInstance() { 24 | if (mInstance == null){ 25 | mInstance = new MediaServerProxy(ServerApplication.getInstance()); 26 | } 27 | return mInstance; 28 | } 29 | 30 | @Override 31 | public boolean startEngine() { 32 | Intent intent = new Intent(DMSService.START_SERVER_ENGINE); 33 | intent.setPackage(mContext.getPackageName()); 34 | mContext.startService(intent); 35 | return true; 36 | } 37 | 38 | @Override 39 | public boolean stopEngine() { 40 | mContext.stopService(new Intent(mContext, DMSService.class)); 41 | return true; 42 | } 43 | 44 | @Override 45 | public boolean restartEngine() { 46 | Intent intent = new Intent(DMSService.RESTART_SERVER_ENGINE); 47 | intent.setPackage(mContext.getPackageName()); 48 | mContext.startService(intent); 49 | return true; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/center/MediaStoreCenter.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.center; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import android.content.Context; 11 | 12 | import com.github.mediaserver.ServerApplication; 13 | import com.github.mediaserver.server.media.IMediaScanListener; 14 | import com.github.mediaserver.server.media.MediaScannerCenter; 15 | import com.github.mediaserver.util.CommonLog; 16 | import com.github.mediaserver.util.FileHelper; 17 | import com.github.mediaserver.util.LogFactory; 18 | 19 | public class MediaStoreCenter implements IMediaScanListener{ 20 | 21 | 22 | private static final CommonLog log = LogFactory.createLog(); 23 | 24 | private static MediaStoreCenter mInstance; 25 | private Context mContext; 26 | 27 | 28 | private String mShareRootPath = ""; 29 | private String mImageFolderPath = ""; 30 | private String mVideoFolderPath = ""; 31 | private String mAudioFolderPath = ""; 32 | 33 | private MediaScannerCenter mMediaScannerCenter; 34 | private Map mMediaStoreMap = new HashMap(); 35 | 36 | 37 | private MediaStoreCenter(Context context) { 38 | mContext = context; 39 | 40 | initData(); 41 | } 42 | 43 | public static synchronized MediaStoreCenter getInstance() { 44 | if (mInstance == null){ 45 | mInstance = new MediaStoreCenter(ServerApplication.getInstance()); 46 | } 47 | return mInstance; 48 | } 49 | 50 | private void initData(){ 51 | mShareRootPath = mContext.getFilesDir().getAbsolutePath()+"/" + "rootFolder"; 52 | mImageFolderPath = mShareRootPath + "/" + "Image"; 53 | mVideoFolderPath = mShareRootPath + "/" + "Video"; 54 | mAudioFolderPath = mShareRootPath + "/" + "Audio"; 55 | mMediaScannerCenter = MediaScannerCenter.getInstance(); 56 | } 57 | 58 | public String getRootDir(){ 59 | return mShareRootPath; 60 | } 61 | public void clearAllData(){ 62 | stopScanMedia(); 63 | clearMediaCache(); 64 | clearWebFolder(); 65 | } 66 | 67 | public boolean createWebFolder(){ 68 | boolean ret = FileHelper.createDirectory(mShareRootPath); 69 | if (!ret){ 70 | return false; 71 | } 72 | 73 | FileHelper.createDirectory(mImageFolderPath); 74 | FileHelper.createDirectory(mVideoFolderPath); 75 | FileHelper.createDirectory(mAudioFolderPath); 76 | 77 | return true; 78 | } 79 | 80 | public boolean clearWebFolder(){ 81 | 82 | long time = System.currentTimeMillis(); 83 | boolean ret = FileHelper.deleteDirectory(mShareRootPath); 84 | long time1 = System.currentTimeMillis(); 85 | log.e("clearWebFolder cost : " + (time1 - time)); 86 | return ret; 87 | } 88 | 89 | public void clearMediaCache(){ 90 | mMediaStoreMap.clear(); 91 | } 92 | 93 | public void doScanMedia(){ 94 | mMediaScannerCenter.startScanThread(this); 95 | } 96 | 97 | public void stopScanMedia(){ 98 | mMediaScannerCenter.stopScanThread(); 99 | while(!mMediaScannerCenter.isThreadOver()){ 100 | try { 101 | Thread.sleep(100); 102 | } catch (InterruptedException e) { 103 | e.printStackTrace(); 104 | } 105 | } 106 | } 107 | 108 | @Override 109 | public void mediaScan(int mediaType, String mediaPath, String mediaName) { 110 | 111 | switch (mediaType) { 112 | case MediaScannerCenter.AUDIO_TYPE: 113 | mapAudio(mediaPath, mediaName); 114 | break; 115 | case MediaScannerCenter.VIDEO_TYPE: 116 | mapVideo(mediaPath, mediaName); 117 | break; 118 | case MediaScannerCenter.IMAGE_TYPE: 119 | mapImage(mediaPath, mediaName); 120 | break; 121 | default: 122 | break; 123 | } 124 | 125 | } 126 | 127 | 128 | private void mapAudio( String mediaPath, String mediaName){ 129 | String webPath = mAudioFolderPath + "/" + mediaName; 130 | mMediaStoreMap.put(mediaPath, webPath); 131 | softLinkMode(mediaPath, webPath); 132 | } 133 | 134 | private void mapVideo( String mediaPath, String mediaName){ 135 | String webPath = mVideoFolderPath + "/" + mediaName; 136 | mMediaStoreMap.put(mediaPath, webPath); 137 | softLinkMode(mediaPath, webPath); 138 | } 139 | 140 | private void mapImage( String mediaPath, String mediaName){ 141 | String webPath = mImageFolderPath + "/" + mediaName; 142 | mMediaStoreMap.put(mediaPath, webPath); 143 | softLinkMode(mediaPath, webPath); 144 | } 145 | 146 | 147 | private boolean softLinkMode(String localPath, String webPath){ 148 | Process p; 149 | int status; 150 | try { 151 | long time = System.currentTimeMillis(); 152 | String cmd = "ln -s " + localPath + " "+ webPath; 153 | p = Runtime.getRuntime().exec(cmd); 154 | releaseProcessStream(p); 155 | 156 | status = p.waitFor(); 157 | if (status == 0) { 158 | return true;//success 159 | } else { 160 | log.e("status = " + status + ", run ln -s failed !localPath = " + localPath); 161 | return false; 162 | } 163 | }catch (Exception e) { 164 | log.e("Catch Exceptino run ln -s failed !localPath = " + localPath); 165 | return false; 166 | } 167 | } 168 | 169 | private void releaseProcessStream(Process p) throws IOException{ 170 | InputStream stderr = p.getErrorStream(); 171 | InputStreamReader isr = new InputStreamReader(stderr); 172 | BufferedReader br = new BufferedReader(isr); 173 | String line = null; 174 | while ( (line = br.readLine()) != null) 175 | System.out.println(line); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/jni/DMSJniInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.jni; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | public class DMSJniInterface { 6 | 7 | static { 8 | System.loadLibrary("git-platinum"); 9 | } 10 | 11 | public static native int startServer(byte[] rootDir,byte[] name ,byte[] uid); 12 | public static native int stopServer(); 13 | 14 | 15 | 16 | public static native boolean enableLogPrint(boolean flag); 17 | 18 | ////////////////////////////////////////////////////////////////////////////////////////// 19 | public static int startServer(String rootDir, String name ,String uid){ 20 | if (rootDir == null){ 21 | rootDir = ""; 22 | } 23 | if (name == null){ 24 | name = ""; 25 | } 26 | if (uid == null){ 27 | uid = ""; 28 | } 29 | int ret = -1; 30 | try { 31 | ret = startServer(rootDir.getBytes("utf-8"), name.getBytes("utf-8"), uid.getBytes("utf-8")); 32 | } catch (UnsupportedEncodingException e) { 33 | e.printStackTrace(); 34 | } 35 | return ret; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/media/IMediaScanListener.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.media; 2 | 3 | public interface IMediaScanListener { 4 | 5 | public void mediaScan(int mediaType, String mediaPath, String mediaName); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/server/media/MediaScannerCenter.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.server.media; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.provider.MediaStore; 6 | 7 | import com.github.mediaserver.ServerApplication; 8 | import com.github.mediaserver.server.center.MediaStoreCenter; 9 | import com.github.mediaserver.util.CommonLog; 10 | import com.github.mediaserver.util.FileHelper; 11 | import com.github.mediaserver.util.LogFactory; 12 | 13 | public class MediaScannerCenter { 14 | 15 | private static final CommonLog log = LogFactory.createLog(); 16 | 17 | public static final int AUDIO_TYPE = 0; 18 | public static final int VIDEO_TYPE = 1; 19 | public static final int IMAGE_TYPE = 2; 20 | 21 | 22 | 23 | String AUDIO_PATH = MediaStore.Audio.AudioColumns.DATA; 24 | String AUDIO_DISPLAYHNAME = MediaStore.Audio.AudioColumns.DISPLAY_NAME; 25 | String AUDIO_COLUMN_STRS[] = {AUDIO_PATH, AUDIO_DISPLAYHNAME}; 26 | 27 | String VIDEO_PATH = MediaStore.Video.VideoColumns.DATA; 28 | String VIDEO_DISPLAYHNAME = MediaStore.Video.VideoColumns.DISPLAY_NAME; 29 | String VIDEO_COLUMN_STRS[] = {VIDEO_PATH, VIDEO_DISPLAYHNAME}; 30 | 31 | String IMAGE_PATH = MediaStore.Images.ImageColumns.DATA; 32 | String IMAGE_DISPLAYHNAME = MediaStore.Images.ImageColumns.DISPLAY_NAME; 33 | String IMAGE_COLUMN_STRS[] = {IMAGE_PATH, IMAGE_DISPLAYHNAME}; 34 | 35 | 36 | private static MediaScannerCenter mInstance; 37 | private Context mContext; 38 | 39 | private ScanMediaThread mediaThread; 40 | 41 | private MediaScannerCenter(Context context) { 42 | mContext = context; 43 | 44 | initData(); 45 | } 46 | 47 | public static synchronized MediaScannerCenter getInstance() { 48 | if (mInstance == null){ 49 | mInstance = new MediaScannerCenter(ServerApplication.getInstance()); 50 | } 51 | return mInstance; 52 | } 53 | 54 | private void initData(){ 55 | 56 | 57 | } 58 | 59 | 60 | public synchronized boolean startScanThread(IMediaScanListener listener){ 61 | if (mediaThread == null || !mediaThread.isAlive()){ 62 | mediaThread = new ScanMediaThread(listener); 63 | mediaThread.start(); 64 | } 65 | 66 | return true; 67 | } 68 | 69 | public synchronized void stopScanThread(){ 70 | if (mediaThread != null){ 71 | if (mediaThread.isAlive()){ 72 | mediaThread.exit(); 73 | } 74 | mediaThread = null; 75 | } 76 | } 77 | 78 | public synchronized boolean isThreadOver(){ 79 | if (mediaThread != null && mediaThread.isAlive()){ 80 | return false; 81 | } 82 | 83 | return true; 84 | } 85 | 86 | private boolean scanMusic(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { 87 | 88 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, 89 | AUDIO_COLUMN_STRS, 90 | null, 91 | null, 92 | AUDIO_DISPLAYHNAME); 93 | 94 | if (cursor != null) 95 | { 96 | int count = cursor.getCount(); 97 | if (count != 0) 98 | { 99 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME); 100 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA); 101 | if (cursor.moveToFirst()) { 102 | do { 103 | if (cancelObser.ifCancel()){ 104 | return false; 105 | } 106 | String srcpath = cursor.getString(_dir_index); 107 | String name = cursor.getString(_name_index); 108 | listener.mediaScan(AUDIO_TYPE, srcpath, name); 109 | 110 | } while (cursor.moveToNext()); 111 | } 112 | } 113 | cursor.close(); 114 | return true; 115 | } 116 | 117 | return false; 118 | } 119 | 120 | private boolean scanVideo(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { 121 | 122 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 123 | VIDEO_COLUMN_STRS, 124 | null, 125 | null, 126 | VIDEO_DISPLAYHNAME); 127 | 128 | if (cursor != null) 129 | { 130 | int count = cursor.getCount(); 131 | if (count != 0) 132 | { 133 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME); 134 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA); 135 | if (cursor.moveToFirst()) { 136 | do { 137 | if (cancelObser.ifCancel()){ 138 | return false; 139 | } 140 | String srcpath = cursor.getString(_dir_index); 141 | String name = cursor.getString(_name_index); 142 | listener.mediaScan(VIDEO_TYPE, srcpath, name); 143 | } while (cursor.moveToNext()); 144 | } 145 | } 146 | cursor.close(); 147 | return true; 148 | } 149 | 150 | return false; 151 | } 152 | 153 | private boolean scanImage(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception { 154 | 155 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 156 | IMAGE_COLUMN_STRS, 157 | null, 158 | null, 159 | IMAGE_DISPLAYHNAME); 160 | 161 | if (cursor != null) 162 | { 163 | int count = cursor.getCount(); 164 | if (count != 0) 165 | { 166 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME); 167 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 168 | if (cursor.moveToFirst()) { 169 | do { 170 | if (cancelObser.ifCancel()){ 171 | return false; 172 | } 173 | String srcpath = cursor.getString(_dir_index); 174 | String name = cursor.getString(_name_index); 175 | listener.mediaScan(IMAGE_TYPE, srcpath, name); 176 | 177 | } while (cursor.moveToNext()); 178 | } 179 | } 180 | cursor.close(); 181 | return true; 182 | } 183 | 184 | return false; 185 | } 186 | 187 | 188 | public class ScanMediaThread extends Thread implements ICancelScanMedia{ 189 | 190 | IMediaScanListener mListener; 191 | boolean exitFlag = false; 192 | 193 | public ScanMediaThread(IMediaScanListener listener){ 194 | mListener = listener; 195 | } 196 | 197 | public void exit(){ 198 | exitFlag = true; 199 | } 200 | 201 | @Override 202 | public void run() { 203 | 204 | try { 205 | scanMusic(mListener, this); 206 | scanVideo(mListener, this); 207 | scanImage(mListener, this); 208 | } catch (Exception e) { 209 | e.printStackTrace(); 210 | } 211 | 212 | super.run(); 213 | } 214 | 215 | @Override 216 | public boolean ifCancel() { 217 | return exitFlag; 218 | } 219 | } 220 | 221 | 222 | public interface ICancelScanMedia{ 223 | public boolean ifCancel(); 224 | } 225 | 226 | 227 | } 228 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/util/CommonLog.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.util; 2 | 3 | import android.util.Log; 4 | 5 | public class CommonLog { 6 | private String tag = "CommonLog"; 7 | public static int logLevel = Log.VERBOSE; 8 | public static boolean isDebug = true; 9 | 10 | public CommonLog() { } 11 | 12 | public CommonLog(String tag) { 13 | this.tag = tag; 14 | } 15 | 16 | public void setTag(String tag) { 17 | this.tag = tag; 18 | } 19 | 20 | private String getFunctionName() { 21 | StackTraceElement[] sts = Thread.currentThread().getStackTrace(); 22 | 23 | if (sts == null) { 24 | return null; 25 | } 26 | 27 | 28 | for (StackTraceElement st:sts) { 29 | if (st.isNativeMethod()) { 30 | continue; 31 | } 32 | 33 | if (st.getClassName().equals(Thread.class.getName())) { 34 | continue; 35 | } 36 | 37 | if (st.getClassName().equals(this.getClass().getName())) { 38 | continue; 39 | } 40 | 41 | return "["+Thread.currentThread().getId()+": "+st.getFileName()+":"+st.getLineNumber()+"]"; 42 | } 43 | 44 | return null; 45 | } 46 | 47 | public void info(Object str) { 48 | if (logLevel <= Log.INFO) { 49 | String name = getFunctionName(); 50 | String ls=(name==null?str.toString():(name+" - "+str)); 51 | Log.i(tag, ls); 52 | } 53 | } 54 | 55 | public void i(Object str) { 56 | if (isDebug) { 57 | info(str); 58 | } 59 | } 60 | 61 | public void verbose(Object str) { 62 | if (logLevel <= Log.VERBOSE) { 63 | String name = getFunctionName(); 64 | String ls=(name==null?str.toString():(name+" - "+str)); 65 | Log.v(tag, ls); 66 | } 67 | } 68 | 69 | public void v(Object str) { 70 | if (isDebug) { 71 | verbose(str); 72 | } 73 | } 74 | 75 | public void warn(Object str) { 76 | if (logLevel <= Log.WARN) { 77 | String name = getFunctionName(); 78 | String ls=(name==null?str.toString():(name+" - "+str)); 79 | Log.w(tag, ls); 80 | } 81 | } 82 | 83 | public void w(Object str) { 84 | if (isDebug) { 85 | warn(str); 86 | } 87 | } 88 | 89 | public void error(Object str) { 90 | if (logLevel <= Log.ERROR) { 91 | String name = getFunctionName(); 92 | String ls=(name==null?str.toString():(name+" - "+str)); 93 | Log.e(tag, ls); 94 | } 95 | } 96 | 97 | public void error(Exception ex) { 98 | if (logLevel <= Log.ERROR) { 99 | StringBuffer sb = new StringBuffer(); 100 | String name = getFunctionName(); 101 | StackTraceElement[] sts = ex.getStackTrace(); 102 | 103 | if (name != null) { 104 | sb.append(name+" - "+ex+"\r\n"); 105 | } else { 106 | sb.append(ex+"\r\n"); 107 | } 108 | 109 | if (sts != null && sts.length > 0) { 110 | for (StackTraceElement st:sts) { 111 | if (st != null) { 112 | sb.append("[ "+st.getFileName()+":"+st.getLineNumber()+" ]\r\n"); 113 | } 114 | } 115 | } 116 | 117 | Log.e(tag, sb.toString()); 118 | } 119 | } 120 | 121 | public void e(Object str) { 122 | if (isDebug) { 123 | error(str); 124 | } 125 | } 126 | 127 | public void e(Exception ex) { 128 | if (isDebug) { 129 | error(ex); 130 | } 131 | } 132 | 133 | public void debug(Object str) { 134 | if (logLevel <= Log.DEBUG) { 135 | String name = getFunctionName(); 136 | String ls = (name == null?str.toString():(name+" - "+str)); 137 | Log.d(tag, ls); 138 | } 139 | } 140 | 141 | public void d(Object str) { 142 | if (isDebug) { 143 | debug(str); 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/util/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.util; 2 | 3 | 4 | 5 | import java.io.InputStream; 6 | import java.net.InetAddress; 7 | import java.net.NetworkInterface; 8 | import java.net.SocketException; 9 | import java.util.Enumeration; 10 | 11 | 12 | import android.content.Context; 13 | import android.content.pm.PackageInfo; 14 | import android.content.pm.PackageManager; 15 | import android.media.AudioManager; 16 | import android.media.MediaPlayer; 17 | import android.net.ConnectivityManager; 18 | import android.net.NetworkInfo; 19 | import android.net.NetworkInfo.State; 20 | import android.net.TrafficStats; 21 | import android.net.wifi.WifiInfo; 22 | import android.net.wifi.WifiManager; 23 | import android.net.wifi.WifiManager.MulticastLock; 24 | import android.os.Environment; 25 | import android.view.Display; 26 | import android.view.WindowManager; 27 | import android.widget.Toast; 28 | 29 | public class CommonUtil { 30 | 31 | private static final CommonLog log = LogFactory.createLog(); 32 | 33 | public static boolean hasSDCard() { 34 | String status = Environment.getExternalStorageState(); 35 | if (!status.equals(Environment.MEDIA_MOUNTED)) { 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | public static String getRootFilePath() { 42 | if (hasSDCard()) { 43 | return Environment.getExternalStorageDirectory().getAbsolutePath() + "/";// filePath:/sdcard/ 44 | } else { 45 | return Environment.getDataDirectory().getAbsolutePath() + "/data/"; // filePath: /data/data/ 46 | } 47 | } 48 | 49 | public static boolean checkNetworkState(Context context){ 50 | boolean netstate = false; 51 | ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 52 | if(connectivity != null) 53 | { 54 | NetworkInfo[] info = connectivity.getAllNetworkInfo(); 55 | if (info != null) { 56 | for (int i = 0; i < info.length; i++) 57 | { 58 | if (info[i].getState() == NetworkInfo.State.CONNECTED) 59 | { 60 | netstate = true; 61 | break; 62 | } 63 | } 64 | } 65 | } 66 | return netstate; 67 | } 68 | 69 | public static String getLocalMacAddress(Context mc){ 70 | String defmac = "00:00:00:00:00:00"; 71 | InputStream input = null; 72 | String wifimac = getWifiMacAddress(mc); 73 | if(null != wifimac){ 74 | if(!wifimac.equals(defmac)) 75 | return wifimac; 76 | } 77 | try{ 78 | 79 | ProcessBuilder builder = new ProcessBuilder( "busybox","ifconfig"); 80 | Process process = builder.start(); 81 | input = process.getInputStream(); 82 | 83 | 84 | 85 | byte[] b = new byte[1024]; 86 | StringBuffer buffer = new StringBuffer(); 87 | while(input.read(b)>0){ 88 | buffer.append(new String(b)); 89 | } 90 | String value = buffer.substring(0); 91 | String systemFlag ="HWaddr "; 92 | int index = value.indexOf(systemFlag); 93 | //List address = new ArrayList (); 94 | if(0"+destUri); 248 | return false; 249 | } 250 | 251 | // check output uri 252 | String path = null; 253 | Uri uri = null; 254 | 255 | String lwUri = destUri.toLowerCase(); 256 | if (lwUri.startsWith("content://")) { 257 | uri = Uri.parse(destUri); 258 | } else if (lwUri.startsWith("file://")) { 259 | uri = Uri.parse(destUri); 260 | path = uri.getPath(); 261 | } else { 262 | path = destUri; 263 | } 264 | 265 | // open output 266 | if (null != path) { 267 | File fl = new File(path); 268 | String pth = path.substring(0, path.lastIndexOf("/")); 269 | File pf = new File(pth); 270 | 271 | if (pf.exists() && !pf.isDirectory()) { 272 | pf.delete(); 273 | } 274 | 275 | pf = new File(pth+File.separator); 276 | 277 | if (!pf.exists()) { 278 | if (!pf.mkdirs()) { 279 | log.e("Can't make dirs, path=" + pth); 280 | } 281 | } 282 | 283 | pf = new File(path); 284 | if (pf.exists()) { 285 | if (pf.isDirectory()) deleteDirectory(path); 286 | else pf.delete(); 287 | } 288 | 289 | os = new FileOutputStream(path); 290 | fl.setLastModified(System.currentTimeMillis()); 291 | } else { 292 | os = new ParcelFileDescriptor.AutoCloseOutputStream(cr.openFileDescriptor(uri, "w")); 293 | } 294 | 295 | // copy file 296 | byte[] dat = new byte[1024]; 297 | int i = is.read(dat); 298 | while(-1 != i) { 299 | os.write(dat, 0, i); 300 | i = is.read(dat); 301 | } 302 | 303 | is.close(); 304 | is = null; 305 | 306 | os.flush(); 307 | os.close(); 308 | os = null; 309 | 310 | return true; 311 | 312 | } catch(Exception ex) { 313 | log.e("Exception, ex: " + ex.toString()); 314 | } finally { 315 | if(null != is) { 316 | try{is.close();} catch(Exception ex) {}; 317 | } 318 | if(null != os) { 319 | try{os.close();} catch(Exception ex) {}; 320 | } 321 | } 322 | return false; 323 | } 324 | 325 | public static byte[] readAll(InputStream is) throws Exception { 326 | ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); 327 | byte[] buf = new byte[1024]; 328 | int c = is.read(buf); 329 | while(-1 != c) { 330 | baos.write(buf, 0, c); 331 | c = is.read(buf); 332 | } 333 | baos.flush(); 334 | baos.close(); 335 | return baos.toByteArray(); 336 | } 337 | 338 | public static byte[] readFile(Context ctx, Uri uri) { 339 | if(null == ctx || null == uri) { 340 | log.e("Invalid param. ctx: "+ctx+", uri: "+uri); 341 | return null; 342 | } 343 | 344 | InputStream is = null; 345 | String scheme = uri.getScheme().toLowerCase(); 346 | if (scheme.equals("file")) { 347 | is = readFile(uri.getPath()); 348 | } 349 | 350 | try { 351 | is = ctx.getContentResolver().openInputStream(uri); 352 | if(null == is) { 353 | return null; 354 | } 355 | 356 | byte[] bret = readAll(is); 357 | is.close(); is = null; 358 | 359 | return bret; 360 | } catch(FileNotFoundException fne) { 361 | log.e("FilNotFoundException, ex: " + fne.toString()); 362 | } catch(Exception ex) { 363 | log.e("Exception, ex: " + ex.toString()); 364 | } finally { 365 | if (null != is) { 366 | try {is.close();} catch(Exception ex) {}; 367 | } 368 | } 369 | return null; 370 | } 371 | 372 | public static boolean writeFile(String filePath, byte[] content) { 373 | if(null == filePath || null == content) { 374 | log.e("Invalid param. filePath: "+filePath+", content: "+content); 375 | return false; 376 | } 377 | 378 | FileOutputStream fos = null; 379 | try{ 380 | String pth = filePath.substring(0, filePath.lastIndexOf("/")); 381 | File pf = null; 382 | pf = new File(pth); 383 | if(pf.exists() && !pf.isDirectory()) { 384 | pf.delete(); 385 | } 386 | pf = new File(filePath); 387 | if(pf.exists()) { 388 | if(pf.isDirectory()) FileHelper.deleteDirectory(filePath); 389 | else pf.delete(); 390 | } 391 | 392 | pf = new File(pth+File.separator); 393 | if (!pf.exists()) { 394 | if (!pf.mkdirs()) { 395 | log.e("Can't make dirs, path=" + pth); 396 | } 397 | } 398 | 399 | fos = new FileOutputStream(filePath); 400 | fos.write(content); 401 | fos.flush(); 402 | fos.close(); fos = null; 403 | pf.setLastModified(System.currentTimeMillis()); 404 | 405 | return true; 406 | 407 | } catch(Exception ex) { 408 | log.e("Exception, ex: " + ex.toString()); 409 | } finally { 410 | if(null != fos) { 411 | try { fos.close(); } catch(Exception ex) {}; 412 | } 413 | } 414 | return false; 415 | } 416 | 417 | /*************ZIP file operation***************/ 418 | public static boolean readZipFile(String zipFileName, StringBuffer crc) { 419 | try { 420 | ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)); 421 | ZipEntry entry; 422 | while ((entry = zis.getNextEntry()) != null) { 423 | long size = entry.getSize(); 424 | crc.append(entry.getCrc() + ", size: " + size); 425 | } 426 | zis.close(); 427 | } catch (Exception ex) { 428 | log.e("Exception: " + ex.toString()); 429 | return false; 430 | } 431 | return true; 432 | } 433 | 434 | public static byte[] readGZipFile (String zipFileName) { 435 | if (fileIsExist(zipFileName)) { 436 | log.i("zipFileName: " + zipFileName); 437 | try { 438 | FileInputStream fin = new FileInputStream(zipFileName); 439 | int size; 440 | byte[] buffer = new byte[1024]; 441 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 442 | while ((size = fin.read(buffer, 0, buffer.length)) != -1) { 443 | baos.write(buffer, 0, size); 444 | } 445 | return baos.toByteArray(); 446 | } catch (Exception ex) { 447 | log.i("read zipRecorder file error"); 448 | } 449 | } 450 | return null; 451 | } 452 | 453 | public static boolean zipFile(String baseDirName, String fileName, String targerFileName) throws IOException { 454 | if (baseDirName == null || "".equals(baseDirName)) { 455 | return false; 456 | } 457 | File baseDir = new File(baseDirName); 458 | if (!baseDir.exists() || !baseDir.isDirectory()) { 459 | return false; 460 | } 461 | 462 | String baseDirPath = baseDir.getAbsolutePath(); 463 | File targerFile = new File(targerFileName); 464 | ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targerFile)); 465 | File file = new File(baseDir, fileName); 466 | 467 | boolean zipResult = false; 468 | if (file.isFile()) { 469 | zipResult = fileToZip(baseDirPath, file, out); 470 | } else { 471 | zipResult = dirToZip(baseDirPath, file, out); 472 | } 473 | out.close(); 474 | return zipResult; 475 | } 476 | 477 | public static boolean unZipFile(String fileName, String unZipDir) throws Exception { 478 | File f = new File(unZipDir); 479 | 480 | if (!f.exists()) { 481 | f.mkdirs(); 482 | } 483 | 484 | BufferedInputStream is = null; 485 | ZipEntry entry; 486 | ZipFile zipfile = new ZipFile(fileName); 487 | Enumeration enumeration = zipfile.entries(); 488 | byte data[] = new byte[FILE_BUFFER_SIZE]; 489 | log.i("unZipDir: " + unZipDir); 490 | 491 | while (enumeration.hasMoreElements()) { 492 | entry = (ZipEntry)enumeration.nextElement(); 493 | 494 | if (entry.isDirectory()) { 495 | File f1 = new File(unZipDir + "/" + entry.getName()); 496 | log.i("entry.isDirectory XXX " + f1.getPath()); 497 | if (!f1.exists()) { 498 | f1.mkdirs(); 499 | } 500 | } else { 501 | is = new BufferedInputStream(zipfile.getInputStream(entry)); 502 | int count; 503 | String name = unZipDir + "/" + entry.getName(); 504 | RandomAccessFile m_randFile = null; 505 | File file = new File(name); 506 | if (file.exists()) { 507 | file.delete(); 508 | } 509 | 510 | file.createNewFile(); 511 | m_randFile = new RandomAccessFile(file, "rw"); 512 | int begin = 0; 513 | 514 | while ((count = is.read(data, 0, FILE_BUFFER_SIZE)) != -1) { 515 | try { 516 | m_randFile.seek(begin); 517 | } catch (Exception ex) { 518 | log.e("exception, ex: " + ex.toString()); 519 | } 520 | 521 | m_randFile.write(data, 0, count); 522 | begin = begin + count; 523 | } 524 | 525 | file.delete(); 526 | m_randFile.close(); 527 | is.close(); 528 | } 529 | } 530 | 531 | return true; 532 | } 533 | 534 | private static boolean fileToZip(String baseDirPath, File file, ZipOutputStream out) throws IOException { 535 | FileInputStream in = null; 536 | ZipEntry entry = null; 537 | 538 | byte[] buffer = new byte[FILE_BUFFER_SIZE]; 539 | int bytes_read; 540 | try { 541 | in = new FileInputStream(file); 542 | entry = new ZipEntry(getEntryName(baseDirPath, file)); 543 | out.putNextEntry(entry); 544 | 545 | while ((bytes_read = in.read(buffer)) != -1) { 546 | out.write(buffer, 0, bytes_read); 547 | } 548 | out.closeEntry(); 549 | in.close(); 550 | } catch (IOException e) { 551 | log.e("Exception, ex: " + e.toString()); 552 | return false; 553 | } finally { 554 | if (out != null) { 555 | out.closeEntry(); 556 | } 557 | 558 | if (in != null) { 559 | in.close(); 560 | } 561 | } 562 | return true; 563 | } 564 | 565 | private static boolean dirToZip(String baseDirPath, File dir, ZipOutputStream out) throws IOException { 566 | if (!dir.isDirectory()) { 567 | return false; 568 | } 569 | 570 | File[] files = dir.listFiles(); 571 | if (files.length == 0) { 572 | ZipEntry entry = new ZipEntry(getEntryName(baseDirPath, dir)); 573 | 574 | try { 575 | out.putNextEntry(entry); 576 | out.closeEntry(); 577 | } catch (IOException e) { 578 | log.e("Exception, ex: " + e.toString()); 579 | } 580 | } 581 | 582 | for (int i = 0; i < files.length; i ++) { 583 | if (files[i].isFile()) { 584 | fileToZip(baseDirPath, files[i], out); 585 | } else { 586 | dirToZip(baseDirPath, files[i], out); 587 | } 588 | } 589 | return true; 590 | } 591 | 592 | private static String getEntryName(String baseDirPath, File file) { 593 | if (!baseDirPath.endsWith(File.separator)) { 594 | baseDirPath = baseDirPath + File.separator; 595 | } 596 | 597 | String filePath = file.getAbsolutePath(); 598 | if (file.isDirectory()) { 599 | filePath = filePath + "/"; 600 | } 601 | 602 | int index = filePath.indexOf(baseDirPath); 603 | return filePath.substring(index + baseDirPath.length()); 604 | } 605 | } -------------------------------------------------------------------------------- /app/src/main/java/com/github/mediaserver/util/LogFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.mediaserver.util; 2 | 3 | 4 | public class LogFactory { 5 | private static final String TAG = "MediaServer"; 6 | private static CommonLog log = null; 7 | 8 | public static CommonLog createLog() { 9 | if (log == null) { 10 | log = new CommonLog(); 11 | } 12 | 13 | log.setTag(TAG); 14 | return log; 15 | } 16 | 17 | public static CommonLog createLog(String tag) { 18 | if (log == null) { 19 | log = new CommonLog(); 20 | } 21 | 22 | if (tag == null || tag.length() < 1) { 23 | log.setTag(TAG); 24 | } else { 25 | log.setTag(tag); 26 | } 27 | return log; 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi/libgit-platinum.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/jniLibs/armeabi/libgit-platinum.so -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/main_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-hdpi/main_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/button_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/button_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/input_disabled.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_disabled.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/input_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/input_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 |