├── .gitignore ├── PushSDK ├── AndroidManifest.xml ├── build.gradle ├── libs │ ├── alicloud-android-sdk-httpdns-1.0.7.jar │ ├── arm64-v8a │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ ├── armeabi-v7a │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ ├── armeabi │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ ├── com.umeng.message_v3.0.6.jar │ ├── mips │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ ├── mips64 │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ ├── utdid4all-1.1.5_proguard.jar │ ├── x86 │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so │ └── x86_64 │ │ ├── libcocklogic-1.1.3.so │ │ └── libtnet-3.1.7.so ├── project.properties └── res │ └── values │ └── string.xml ├── README.md ├── app ├── .gitignore ├── Piebald_v2.0.0.apk ├── app-v1.3.0.apk ├── app-v1.3.1.apk ├── build.gradle ├── libs │ ├── BmobSDK_3.5.1_20160719.jar │ ├── YoumiSdk_v6.4.3_2016-08-16.jar │ ├── arm64-v8a │ │ └── libbmob.so │ ├── armeabi-v7a │ │ └── libbmob.so │ ├── armeabi │ │ └── libbmob.so │ ├── libammsdk.jar │ ├── mips │ │ └── libbmob.so │ ├── mips64 │ │ └── libbmob.so │ ├── rxandroid-1.2.0.jar │ ├── universal-image-loader-1.9.5.jar │ ├── volley.jar │ ├── x86 │ │ └── libbmob.so │ └── x86_64 │ │ └── libbmob.so ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── blackzheng │ │ └── me │ │ └── piebald │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── dex.jar │ │ └── fonts │ │ │ ├── RobotoCondensed-Bold.ttf │ │ │ └── RobotoCondensed-BoldItalic.ttf │ ├── java │ │ └── com │ │ │ └── blackzheng │ │ │ └── me │ │ │ └── piebald │ │ │ ├── App.java │ │ │ ├── api │ │ │ ├── UnsplashAPI.java │ │ │ └── UnsplashService.java │ │ │ ├── dao │ │ │ ├── BaseDataHelper.java │ │ │ ├── CollectionDataHelper.java │ │ │ ├── ContentDataHelper.java │ │ │ ├── DBHelper.java │ │ │ ├── DataProvider.java │ │ │ ├── PhotoCollectionDataHelper.java │ │ │ ├── UserAlbumDataHelper.java │ │ │ └── UserCollectionsDataHelper.java │ │ │ ├── data │ │ │ └── ImageCacheManager.java │ │ │ ├── model │ │ │ ├── BaseModel.java │ │ │ ├── Collection.java │ │ │ ├── Feedback.java │ │ │ ├── Photo.java │ │ │ └── User.java │ │ │ ├── ui │ │ │ ├── AboutActivity.java │ │ │ ├── BaseActivity.java │ │ │ ├── CollectionActivity.java │ │ │ ├── FeedbackActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── PhotoDetailActivity.java │ │ │ ├── PhotoZoomingActivity.java │ │ │ ├── SettingActivity.java │ │ │ ├── ShareSelectActivity.java │ │ │ ├── UserPageActivity.java │ │ │ ├── adapter │ │ │ │ ├── BaseAbstractRecycleCursorAdapter.java │ │ │ │ ├── BaseListenerAdapter.java │ │ │ │ ├── CollectionsListAdapter.java │ │ │ │ ├── ContentAdapter.java │ │ │ │ ├── CursorFilter.java │ │ │ │ └── UserPhotosAdapter.java │ │ │ ├── fragment │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── CategoryContentFragment.java │ │ │ │ ├── CollectionsFragment.java │ │ │ │ ├── ContentFragment.java │ │ │ │ ├── UserCollectionsFragment.java │ │ │ │ └── UserPhotosFragment.java │ │ │ └── listener │ │ │ │ └── OnDoubleClickListener.java │ │ │ ├── util │ │ │ ├── BitmapUtil.java │ │ │ ├── CacheUtil.java │ │ │ ├── Constants.java │ │ │ ├── Decoder.java │ │ │ ├── DensityUtils.java │ │ │ ├── Downloader.java │ │ │ ├── DrawableUtil.java │ │ │ ├── LogHelper.java │ │ │ ├── NetworkUtils.java │ │ │ ├── PathUtils.java │ │ │ ├── ResourceUtil.java │ │ │ ├── ShareBitmapHolder.java │ │ │ ├── ShareImgToWX.java │ │ │ ├── StringUtil.java │ │ │ ├── TaskUtils.java │ │ │ ├── ToastUtils.java │ │ │ └── database │ │ │ │ ├── Column.java │ │ │ │ └── SQLiteTable.java │ │ │ └── view │ │ │ └── HideableToolbar.java │ └── res │ │ ├── anim │ │ ├── push_bottom_in.xml │ │ ├── push_bottom_out.xml │ │ ├── slide_in_from_left.xml │ │ ├── slide_in_from_right.xml │ │ ├── slide_out_to_left.xml │ │ └── slide_out_to_right.xml │ │ ├── drawable │ │ ├── border.xml │ │ ├── border_thin.xml │ │ ├── default_profile.jpg │ │ ├── dissatisfied.png │ │ ├── divider.xml │ │ ├── error_drawable.xml │ │ ├── like.png │ │ ├── moments.png │ │ ├── noti_small.png │ │ ├── profile.jpg │ │ ├── shade.xml │ │ └── wechat.png │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_collection.xml │ │ ├── activity_feedback.xml │ │ ├── activity_main.xml │ │ ├── activity_setting.xml │ │ ├── activity_share_select.xml │ │ ├── activity_user_album.xml │ │ ├── ad_layout.xml │ │ ├── album_photo_item.xml │ │ ├── collection_headerview.xml │ │ ├── collection_item.xml │ │ ├── collections_list_item.xml │ │ ├── divider_layout.xml │ │ ├── drawer_header.xml │ │ ├── drawer_item.xml │ │ ├── emptyview.xml │ │ ├── notification_view.xml │ │ ├── photo_detail_layout.xml │ │ ├── photo_zooming_layout.xml │ │ ├── recycler_item.xml │ │ ├── super_recyclerview.xml │ │ ├── toolbar.xml │ │ ├── user_album_headerview.xml │ │ └── view_more_progress.xml │ │ ├── menu │ │ ├── menu_main.xml │ │ ├── menu_share.xml │ │ └── nav_menu.xml │ │ ├── mipmap-hdpi │ │ ├── building.png │ │ ├── default_drawer_header.jpg │ │ ├── dissatisfied.png │ │ ├── download.png │ │ ├── foodanddrink.png │ │ ├── ic_launcher.png │ │ ├── icn_close.png │ │ ├── item_down.png │ │ ├── item_up.png │ │ ├── like.png │ │ ├── location.png │ │ ├── n.png │ │ ├── nature.png │ │ ├── object.png │ │ ├── people.png │ │ ├── sentiment_dissatisfied.png │ │ ├── share.png │ │ ├── splash.jpg │ │ └── technology.png │ │ ├── mipmap-mdpi │ │ ├── building.png │ │ ├── default_drawer_header.jpg │ │ ├── dissatisfied.png │ │ ├── download.png │ │ ├── foodanddrink.png │ │ ├── ic_launcher.png │ │ ├── icn_close.png │ │ ├── like.png │ │ ├── location.png │ │ ├── n.png │ │ ├── nature.png │ │ ├── object.png │ │ ├── people.png │ │ ├── sentiment_dissatisfied.png │ │ ├── share.png │ │ ├── splash.jpg │ │ └── technology.png │ │ ├── mipmap-xhdpi │ │ ├── building.png │ │ ├── default_drawer_header.jpg │ │ ├── dissatisfied.png │ │ ├── download.png │ │ ├── foodanddrink.png │ │ ├── ic_launcher.png │ │ ├── icn_close.png │ │ ├── like.png │ │ ├── location.png │ │ ├── n.png │ │ ├── nature.png │ │ ├── object.png │ │ ├── people.png │ │ ├── sentiment_dissatisfied.png │ │ ├── share.png │ │ ├── splash.jpg │ │ └── technology.png │ │ ├── mipmap-xxhdpi │ │ ├── building.png │ │ ├── default_drawer_header.jpg │ │ ├── dissatisfied.png │ │ ├── download.png │ │ ├── foodanddrink.png │ │ ├── ic_launcher.png │ │ ├── icn_close.png │ │ ├── like.png │ │ ├── location.png │ │ ├── n.png │ │ ├── nature.png │ │ ├── object.png │ │ ├── people.png │ │ ├── sentiment_dissatisfied.png │ │ ├── share.png │ │ ├── splash.jpg │ │ └── technology.png │ │ ├── mipmap-xxxhdpi │ │ ├── building.png │ │ ├── default_drawer_header.jpg │ │ ├── dissatisfied.png │ │ ├── download.png │ │ ├── foodanddrink.png │ │ ├── ic_launcher.png │ │ ├── icn_close.png │ │ ├── like.png │ │ ├── location.png │ │ ├── n.png │ │ ├── nature.png │ │ ├── object.png │ │ ├── people.png │ │ ├── sentiment_dissatisfied.png │ │ ├── share.png │ │ ├── splash.jpg │ │ └── technology.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values-zh │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── blackzheng │ └── me │ └── piebald │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── build.gradle ├── gradle.properties └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── net │ │ │ └── rdrei │ │ │ └── android │ │ │ └── dirchooser │ │ │ ├── DirectoryChooserActivity.java │ │ │ ├── DirectoryChooserConfig.java │ │ │ └── DirectoryChooserFragment.java │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_action_create.png │ │ ├── ic_action_create_light.png │ │ ├── navigation_up.png │ │ └── navigation_up_light.png │ │ ├── drawable-ldpi │ │ ├── navigation_up.png │ │ └── navigation_up_light.png │ │ ├── drawable-mdpi │ │ ├── ic_action_create.png │ │ ├── ic_action_create_light.png │ │ ├── navigation_up.png │ │ └── navigation_up_light.png │ │ ├── drawable-xhdpi │ │ ├── ic_action_create.png │ │ ├── ic_action_create_light.png │ │ ├── navigation_up.png │ │ └── navigation_up_light.png │ │ ├── drawable-xxhdpi │ │ ├── ic_action_create.png │ │ └── ic_action_create_light.png │ │ ├── drawable │ │ └── borderless_button.xml │ │ ├── layout-v11 │ │ └── directory_chooser.xml │ │ ├── layout │ │ ├── dialog_new_folder.xml │ │ ├── directory_chooser.xml │ │ └── directory_chooser_activity.xml │ │ ├── menu │ │ └── directory_chooser.xml │ │ ├── values-de │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-et │ │ └── strings.xml │ │ ├── values-fr │ │ └── strings.xml │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-sk │ │ └── strings.xml │ │ ├── values-v11 │ │ └── colors.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ ├── java │ ├── AndroidManifest.xml │ └── net │ │ └── rdrei │ │ └── android │ │ └── dirchooser │ │ ├── DirectoryChooserActivityTest.java │ │ ├── DirectoryChooserFragmentTest.java │ │ └── TestMenuItem.java │ └── resources │ └── robolectric.properties ├── screenshots ├── ad.jpg ├── screenshot1.jpg ├── screenshot2.jpg ├── screenshot3.jpg ├── screenshot4.jpg ├── screenshot5.jpg └── screenshot6.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.ap_ 3 | 4 | # files for the dex VM 5 | *.dex 6 | 7 | # Java class files 8 | *.class 9 | 10 | # generated files 11 | bin/ 12 | gen/ 13 | 14 | # Local configuration file (sdk path, etc) 15 | local.properties 16 | 17 | # Proguard folder generated by Eclipse 18 | proguard/ 19 | 20 | # Ignore gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | .settings/ 28 | 29 | # Intellij project files 30 | *.iml 31 | *.ipr 32 | *.iws 33 | .idea/ 34 | 35 | # Mac system files 36 | .DS_Store -------------------------------------------------------------------------------- /PushSDK/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 11 9 | targetSdkVersion 22 10 | } 11 | 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 16 | } 17 | debug { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 20 | } 21 | } 22 | 23 | sourceSets { 24 | main { 25 | manifest.srcFile 'AndroidManifest.xml' 26 | java.srcDirs = ['src'] 27 | resources.srcDirs = ['src'] 28 | aidl.srcDirs = ['src'] 29 | renderscript.srcDirs = ['src'] 30 | res.srcDirs = ['res'] 31 | assets.srcDirs = ['assets'] 32 | jniLibs.srcDirs = ['libs'] 33 | } 34 | 35 | // Move the tests to tests/java, tests/res, etc... 36 | instrumentTest.setRoot('tests') 37 | 38 | // Move the build types to build-types/ 39 | // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... 40 | // This moves them out of them default location under src//... which would 41 | // conflict with src/ being used by the main source set. 42 | // Adding new build types or product flavors should be accompanied 43 | // by a similar customization. 44 | debug.setRoot('build-types/debug') 45 | release.setRoot('build-types/release') 46 | } 47 | } 48 | 49 | dependencies { 50 | compile fileTree(dir: 'libs', include: ['*.jar']) 51 | } 52 | -------------------------------------------------------------------------------- /PushSDK/libs/alicloud-android-sdk-httpdns-1.0.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/alicloud-android-sdk-httpdns-1.0.7.jar -------------------------------------------------------------------------------- /PushSDK/libs/arm64-v8a/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/arm64-v8a/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/arm64-v8a/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/arm64-v8a/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/armeabi-v7a/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/armeabi-v7a/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/armeabi-v7a/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/armeabi-v7a/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/armeabi/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/armeabi/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/armeabi/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/armeabi/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/com.umeng.message_v3.0.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/com.umeng.message_v3.0.6.jar -------------------------------------------------------------------------------- /PushSDK/libs/mips/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/mips/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/mips/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/mips/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/mips64/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/mips64/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/mips64/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/mips64/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/utdid4all-1.1.5_proguard.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/utdid4all-1.1.5_proguard.jar -------------------------------------------------------------------------------- /PushSDK/libs/x86/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/x86/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/x86/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/x86/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/libs/x86_64/libcocklogic-1.1.3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/x86_64/libcocklogic-1.1.3.so -------------------------------------------------------------------------------- /PushSDK/libs/x86_64/libtnet-3.1.7.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/PushSDK/libs/x86_64/libtnet-3.1.7.so -------------------------------------------------------------------------------- /PushSDK/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 use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-19 12 | android.library=true 13 | -------------------------------------------------------------------------------- /PushSDK/res/values/string.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Piebald-Android 2 | ===================== 3 | 4 | Piebald is an application for appreciation and downloading of stunning photograph. [Unsplash.com](https://unsplash.com/) is the image source. 5 | This is my first project for development practice. I'm sure that there are many defects in this project. I will apreciate your advices or criticisms. And I 'm glad if somebody help me to perfect Piebald. 6 | 7 | ## Preview 8 | screenshot 9 | 10 | screenshot screenshot 11 | 12 | screenshotscreenshot 13 | 14 | screenshotscreenshot 15 | 16 | 17 | Get it on Google Play 18 | 19 | [Download Demo](https://github.com/BlackZheng/Piebald/releases/download/v2.0.3/Piebald_v2.0.3.apk) 20 | 21 | 22 | ## Credits 23 | Thanks [Frank-Zhu](https://github.com/Frank-Zhu) for the achievement of BaseAbstractRecycleCursorAdapter 24 | and [stormzhang](https://github.com/stormzhang) for [9gag](https://github.com/stormzhang/9GAG) which provided me the inspiration! 25 | 26 | 27 | ## Third-party Libraries 28 | 29 | * [Volley](https://android.googlesource.com/platform/frameworks/volley) 30 | 31 | * [Gson](https://github.com/google/gson) 32 | 33 | * [UniversalImageLoader](https://github.com/nostra13/Android-Universal-Image-Loader) 34 | 35 | * [SuperRecyclerView](https://github.com/Malinskiy/SuperRecyclerView) 36 | 37 | * [CircleImageView](https://github.com/hdodenhof/CircleImageView) 38 | 39 | * [PhotoView](https://github.com/chrisbanes/PhotoView) 40 | 41 | * [CircleProgress](https://github.com/lzyzsd/CircleProgress) 42 | 43 | * [recyclerview-animators](https://github.com/wasabeef/recyclerview-animators) 44 | 45 | * [Android-DirectoryChooser](https://github.com/passy/Android-DirectoryChooser) 46 | 47 | * [retrofit](https://github.com/square/retrofit) 48 | 49 | * [RoundedImageView](https://github.com/vinc3m1/RoundedImageView) 50 | 51 | * [PermissionsDispatcher](https://github.com/hotchemi/PermissionsDispatcher) 52 | 53 | * [FileDownloader](https://github.com/lingochamp/FileDownloader) 54 | 55 | * [Calligraphy](https://github.com/chrisjenx/Calligraphy) 56 | 57 | * [RxJava](https://github.com/ReactiveX/RxJava) 58 | 59 | ## Developer 60 | 61 | * [BlackZheng](https://github.com/BlackZheng) 62 | * Email:blackzheng22@gmail.com 63 | 64 | License 65 | ============ 66 | 67 | Copyright 2016 BlackZheng 68 | 69 | Licensed under the GNU General Public License, Version 3.0 (the "License"); 70 | you may not use this file except in compliance with the License. 71 | You may obtain a copy of the License at 72 | 73 | http://www.gnu.org/licenses/gpl-3.0.html 74 | 75 | Unless required by applicable law or agreed to in writing, software 76 | distributed under the License is distributed on an "AS IS" BASIS, 77 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 78 | See the License for the specific language governing permissions and 79 | limitations under the License. -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/Piebald_v2.0.0.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/Piebald_v2.0.0.apk -------------------------------------------------------------------------------- /app/app-v1.3.0.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/app-v1.3.0.apk -------------------------------------------------------------------------------- /app/app-v1.3.1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/app-v1.3.1.apk -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'android-apt' 3 | 4 | def releaseTime() { 5 | return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) 6 | } 7 | repositories { 8 | jcenter() 9 | mavenCentral() 10 | maven { url "http://dl.bintray.com/jjhesk/maven" } 11 | maven { url 'http://guardian.github.com/maven/repo-releases' } 12 | maven { url "https://jitpack.io" } 13 | } 14 | android { 15 | signingConfigs { 16 | release { 17 | keyAlias 'key_of_black' 18 | keyPassword 'zhj1562786' 19 | storeFile file('F:/projects/key.jks') 20 | storePassword 'zhj1562786' 21 | } 22 | } 23 | compileSdkVersion 23 24 | buildToolsVersion "23.0.2" 25 | useLibrary 'org.apache.http.legacy' 26 | defaultConfig { 27 | applicationId "com.blackzheng.me.piebald" 28 | minSdkVersion 16 29 | targetSdkVersion 23 30 | versionCode 10 31 | versionName "2.0.3" 32 | manifestPlaceholders = [UMENG_CHANNEL_VALUE: "black_zheng"] 33 | } 34 | buildTypes { 35 | release { 36 | // 不显示Log 37 | buildConfigField "boolean", "LOG_DEBUG", "false" 38 | 39 | zipAlignEnabled true 40 | // 移除无用的resource文件 41 | shrinkResources true 42 | minifyEnabled true 43 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 44 | signingConfig signingConfigs.release 45 | applicationVariants.all { variant -> 46 | variant.outputs.each { output -> 47 | def outputFile = output.outputFile 48 | if (outputFile != null && outputFile.name.endsWith('.apk')) { 49 | // 输出apk名称为Piebald_v1.0_2015-01-15_wandoujia.apk 50 | def fileName = "Piebald_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk" 51 | output.outputFile = new File(outputFile.parent, fileName) 52 | } 53 | } 54 | } 55 | } 56 | } 57 | sourceSets { 58 | main.jniLibs.srcDirs = ['libs'] 59 | } 60 | sourceSets { main { assets.srcDirs = ['src/main/assets', 'src/main/assets/'] } } 61 | productFlavors { 62 | no_market {} 63 | wandoujia {} 64 | tencent {} 65 | samsung {} 66 | huawei {} 67 | google {} 68 | xiaomi {} 69 | meizu {} 70 | baidu {} 71 | gfan {} 72 | _360 {} 73 | uc {} 74 | 75 | productFlavors.all { flavor -> 76 | flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] 77 | } 78 | 79 | } 80 | } 81 | allprojects { 82 | gradle.projectsEvaluated { 83 | tasks.withType(JavaCompile) { 84 | options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" 85 | } 86 | } 87 | } 88 | dependencies { 89 | compile fileTree(include: ['*.jar'], dir: 'libs') 90 | testCompile 'junit:junit:4.12' 91 | compile 'com.android.support:appcompat-v7:23.2.1' 92 | compile 'com.android.support:design:23.2.1' 93 | compile 'com.android.support:cardview-v7:23.+' 94 | compile 'com.malinskiy:superrecyclerview:1.1.4' 95 | compile 'de.hdodenhof:circleimageview:2.0.0' 96 | compile 'com.commit451:PhotoView:1.2.5' 97 | compile 'com.github.lzyzsd:circleprogress:1.1.0@aar' 98 | compile 'jp.wasabeef:recyclerview-animators:2.2.1' 99 | compile 'net.qiujuer.genius:blur:2.0.0' 100 | compile 'uk.co.chrisjenx:calligraphy:2.2.0' 101 | compile 'com.umeng.analytics:analytics:latest.integration' 102 | compile project(':library') 103 | compile 'com.liulishuo.filedownloader:library:0.3.1' 104 | compile 'com.github.hotchemi:permissionsdispatcher:2.1.3' 105 | compile 'com.squareup.retrofit2:retrofit:2.1.0' 106 | compile 'com.google.code.gson:gson:2.8.0' 107 | compile 'com.squareup.retrofit2:converter-gson:+' 108 | compile 'com.squareup.retrofit2:adapter-rxjava:+' 109 | compile 'io.reactivex:rxjava:+' 110 | apt 'com.github.hotchemi:permissionsdispatcher-processor:2.1.3' 111 | compile 'com.makeramen:roundedimageview:2.3.0' 112 | compile project(':PushSDK') 113 | } 114 | -------------------------------------------------------------------------------- /app/libs/BmobSDK_3.5.1_20160719.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/BmobSDK_3.5.1_20160719.jar -------------------------------------------------------------------------------- /app/libs/YoumiSdk_v6.4.3_2016-08-16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/YoumiSdk_v6.4.3_2016-08-16.jar -------------------------------------------------------------------------------- /app/libs/arm64-v8a/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/arm64-v8a/libbmob.so -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/armeabi-v7a/libbmob.so -------------------------------------------------------------------------------- /app/libs/armeabi/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/armeabi/libbmob.so -------------------------------------------------------------------------------- /app/libs/libammsdk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/libammsdk.jar -------------------------------------------------------------------------------- /app/libs/mips/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/mips/libbmob.so -------------------------------------------------------------------------------- /app/libs/mips64/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/mips64/libbmob.so -------------------------------------------------------------------------------- /app/libs/rxandroid-1.2.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/rxandroid-1.2.0.jar -------------------------------------------------------------------------------- /app/libs/universal-image-loader-1.9.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/universal-image-loader-1.9.5.jar -------------------------------------------------------------------------------- /app/libs/volley.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/volley.jar -------------------------------------------------------------------------------- /app/libs/x86/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/x86/libbmob.so -------------------------------------------------------------------------------- /app/libs/x86_64/libbmob.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/libs/x86_64/libbmob.so -------------------------------------------------------------------------------- /app/src/androidTest/java/com/blackzheng/me/piebald/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald; 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 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 27 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 46 | 50 | 54 | 58 | 61 | 66 | 69 | 71 | 74 | 75 | 76 | 77 | 80 | 81 | 84 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /app/src/main/assets/dex.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/assets/dex.jar -------------------------------------------------------------------------------- /app/src/main/assets/fonts/RobotoCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/assets/fonts/RobotoCondensed-Bold.ttf -------------------------------------------------------------------------------- /app/src/main/assets/fonts/RobotoCondensed-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/assets/fonts/RobotoCondensed-BoldItalic.ttf -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/api/UnsplashService.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.api; 2 | 3 | import com.blackzheng.me.piebald.model.Collection; 4 | import com.blackzheng.me.piebald.model.Photo; 5 | import com.blackzheng.me.piebald.model.User; 6 | 7 | import java.util.List; 8 | 9 | import retrofit2.Call; 10 | import retrofit2.http.GET; 11 | import retrofit2.http.Path; 12 | import retrofit2.http.Query; 13 | import rx.Observable; 14 | 15 | /** 16 | * Created by BlackZheng on 2016/12/1. 17 | */ 18 | 19 | public interface UnsplashService { 20 | 21 | @GET("photos") 22 | Observable> getLatestPhotos(@Query("page") String page, @Query("client_id") String client_id); 23 | 24 | @GET("categories/{category_id}/photos") 25 | Observable> getPhotosByCategory(@Path("category_id") String category_id, @Query("page") String page, @Query("client_id") String client_id); 26 | 27 | @GET("users/{username}/photos") 28 | Observable> getPhotosByUser(@Path("username") String username, @Query("page") int page, @Query("client_id") String client_id); 29 | 30 | @GET("users/{username}/collections") 31 | Observable> getCollectionsByUser(@Path("username") String username, @Query("page") String page, @Query("client_id") String client_id); 32 | 33 | @GET("photos/{id}") 34 | Observable getPhoto(@Path("id") String id, @Query("client_id") String client_id); 35 | 36 | @GET("users/{username}") 37 | Observable getUserByUsername(@Path("username") String username, @Query("client_id") String client_id); 38 | 39 | @GET("collections/{type}") 40 | Observable> getCollections(@Path("type") String type, @Query("page") String page, @Query("client_id") String client_id); 41 | 42 | @GET("collections/{id}") 43 | Observable getFeatureCollection(@Path("id") String id, @Query("client_id") String client_id); 44 | 45 | @GET("collections/curated/{id}") 46 | Observable getCuratedCollection(@Path("id") String id, @Query("client_id") String client_id); 47 | @GET("collections/{id}/photos") 48 | Observable> getFeaturePhotos(@Path("id") String id, @Query("page") int page, @Query("client_id") String client_id); 49 | 50 | @GET("collections/curated/{id}/photos") 51 | Observable> getCuratedPhotos(@Path("id") String id, @Query("page") int page, @Query("client_id") String client_id); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/dao/BaseDataHelper.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.dao; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | import android.support.v4.content.CursorLoader; 8 | 9 | /** 10 | * Created by BlackZheng on 2016/4/6. 11 | */ 12 | public abstract class BaseDataHelper { 13 | private Context mContext; 14 | 15 | public BaseDataHelper(Context context) { 16 | mContext = context; 17 | } 18 | 19 | public Context getContext() { 20 | return mContext; 21 | } 22 | 23 | protected abstract Uri getContentUri(); 24 | 25 | public void notifyChange() { 26 | mContext.getContentResolver().notifyChange(getContentUri(), null); 27 | } 28 | 29 | protected final Cursor query(Uri uri, String[] projection, String selection, 30 | String[] selectionArgs, String sortOrder) { 31 | return mContext.getContentResolver().query(uri, projection, selection, selectionArgs, 32 | sortOrder); 33 | } 34 | 35 | protected final Cursor query(String[] projection, String selection, String[] selectionArgs, 36 | String sortOrder) { 37 | return mContext.getContentResolver().query(getContentUri(), projection, selection, 38 | selectionArgs, sortOrder); 39 | } 40 | 41 | protected final Uri insert(ContentValues values) { 42 | return mContext.getContentResolver().insert(getContentUri(), values); 43 | } 44 | 45 | protected final int bulkInsert(ContentValues[] values) { 46 | return mContext.getContentResolver().bulkInsert(getContentUri(), values); 47 | } 48 | 49 | protected final int update(ContentValues values, String where, String[] whereArgs) { 50 | return mContext.getContentResolver().update(getContentUri(), values, where, whereArgs); 51 | } 52 | 53 | protected final int delete(Uri uri, String selection, String[] selectionArgs) { 54 | return mContext.getContentResolver().delete(getContentUri(), selection, selectionArgs); 55 | } 56 | 57 | protected final Cursor getList(String[] projection, String selection, String[] selectionArgs, 58 | String sortOrder) { 59 | return mContext.getContentResolver().query(getContentUri(), projection, selection, 60 | selectionArgs, sortOrder); 61 | } 62 | 63 | public abstract CursorLoader getCursorLoader(); 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/dao/DBHelper.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.dao; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | /** 8 | * Created by BlackZheng on 2016/4/6. 9 | */ 10 | public class DBHelper extends SQLiteOpenHelper { 11 | // 数据库名 12 | private static final String DB_NAME = "piebald.db"; 13 | 14 | // 数据库版本 15 | private static final int VERSION = 4; 16 | 17 | public DBHelper(Context context) { 18 | super(context, DB_NAME, null, VERSION); 19 | } 20 | 21 | @Override 22 | public void onCreate(SQLiteDatabase db) { 23 | ContentDataHelper.ContentDBInfo.TABLE.create(db); 24 | UserAlbumDataHelper.ContentDBInfo.TABLE.create(db); 25 | CollectionDataHelper.ContentDBInfo.TABLE.create(db); 26 | PhotoCollectionDataHelper.ContentDBInfo.TABLE.create(db); 27 | UserCollectionsDataHelper.ContentDBInfo.TABLE.create(db); 28 | } 29 | 30 | @Override 31 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 32 | switch (oldVersion){ 33 | case 1: 34 | UserAlbumDataHelper.ContentDBInfo.TABLE.create(db); 35 | CollectionDataHelper.ContentDBInfo.TABLE.create(db); 36 | PhotoCollectionDataHelper.ContentDBInfo.TABLE.create(db); 37 | UserCollectionsDataHelper.ContentDBInfo.TABLE.create(db); 38 | break; 39 | case 2: 40 | CollectionDataHelper.ContentDBInfo.TABLE.create(db); 41 | PhotoCollectionDataHelper.ContentDBInfo.TABLE.create(db); 42 | UserCollectionsDataHelper.ContentDBInfo.TABLE.create(db); 43 | break; 44 | case 3: 45 | UserCollectionsDataHelper.ContentDBInfo.TABLE.create(db); 46 | break; 47 | default: 48 | break; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/dao/PhotoCollectionDataHelper.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.dao; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.net.Uri; 7 | import android.provider.BaseColumns; 8 | import android.support.v4.content.CursorLoader; 9 | 10 | import com.blackzheng.me.piebald.model.Photo; 11 | import com.blackzheng.me.piebald.util.database.Column; 12 | import com.blackzheng.me.piebald.util.database.SQLiteTable; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by BlackZheng on 2016/8/28. 19 | */ 20 | public class PhotoCollectionDataHelper extends BaseDataHelper { 21 | 22 | private String mCollectionID; 23 | 24 | public PhotoCollectionDataHelper(Context context, String id) { 25 | super(context); 26 | mCollectionID = id; 27 | } 28 | 29 | @Override 30 | protected Uri getContentUri() { 31 | return DataProvider.PHOTO_COLLECTION_URI; 32 | } 33 | 34 | private ContentValues getContentValues(Photo photo) { 35 | ContentValues values = new ContentValues(); 36 | values.put(ContentDBInfo.ID, String.valueOf(photo.id)); 37 | values.put(ContentDBInfo.COLLECTION, mCollectionID); 38 | values.put(ContentDBInfo.JSON, photo.toJosn()); 39 | return values; 40 | } 41 | 42 | public void bulkInsert(List photos) { 43 | ArrayList contentValues = new ArrayList(); 44 | for (Photo photo : photos) { 45 | ContentValues values = getContentValues(photo); 46 | contentValues.add(values); 47 | } 48 | ContentValues[] valueArray = new ContentValues[contentValues.size()]; 49 | bulkInsert(contentValues.toArray(valueArray)); 50 | } 51 | 52 | public int deleteAll() { 53 | synchronized (DataProvider.DBLock) { 54 | DBHelper mDBHelper = DataProvider.getDBHelper(); 55 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 56 | int row = db.delete(ContentDBInfo.TABLE_NAME, ContentDBInfo.COLLECTION + "=?", new String[] { 57 | mCollectionID 58 | }); 59 | return row; 60 | } 61 | } 62 | 63 | /** 64 | * 清空该表格的所有数据,用于清楚缓存 65 | * @return 66 | */ 67 | public static int deleteAllRows(){ 68 | synchronized (DataProvider.DBLock) { 69 | DBHelper mDBHelper = DataProvider.getDBHelper(); 70 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 71 | int row = db.delete(ContentDBInfo.TABLE_NAME, null, null); 72 | return row; 73 | } 74 | } 75 | 76 | @Override 77 | public CursorLoader getCursorLoader() { 78 | return new CursorLoader(getContext(), getContentUri(), null, ContentDBInfo.COLLECTION + "=?", 79 | new String[] { 80 | mCollectionID 81 | }, ContentDBInfo._ID + " ASC"); 82 | } 83 | 84 | public static final class ContentDBInfo implements BaseColumns { 85 | private ContentDBInfo() { 86 | } 87 | 88 | public static final String TABLE_NAME = "photo_collection"; 89 | 90 | public static final String ID = "id"; 91 | 92 | public static final String COLLECTION = "collection"; 93 | 94 | public static final String JSON = "json"; 95 | 96 | public static final SQLiteTable TABLE = new SQLiteTable(TABLE_NAME) 97 | .addColumn(ID, Column.DataType.TEXT) 98 | .addColumn(COLLECTION, Column.DataType.TEXT).addColumn(JSON, Column.DataType.TEXT); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/dao/UserAlbumDataHelper.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.dao; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.net.Uri; 8 | import android.provider.BaseColumns; 9 | import android.support.v4.content.CursorLoader; 10 | 11 | import com.blackzheng.me.piebald.model.Photo; 12 | import com.blackzheng.me.piebald.util.database.Column; 13 | import com.blackzheng.me.piebald.util.database.SQLiteTable; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * Created by BlackZheng on 2016/8/17. 20 | */ 21 | public class UserAlbumDataHelper extends BaseDataHelper { 22 | 23 | private String mUser; 24 | 25 | public UserAlbumDataHelper(Context context, String username) { 26 | super(context); 27 | mUser = username; 28 | } 29 | //Need to change 30 | @Override 31 | protected Uri getContentUri() { 32 | return DataProvider.USERALBUM_URI; 33 | } 34 | 35 | private ContentValues getContentValues(Photo photo) { 36 | ContentValues values = new ContentValues(); 37 | values.put(ContentDBInfo.ID, photo.id); 38 | values.put(ContentDBInfo.USER, photo.user.username); 39 | values.put(ContentDBInfo.JSON, photo.toJosn()); 40 | return values; 41 | } 42 | 43 | public Photo query(long id) { 44 | Photo photo = null; 45 | Cursor cursor = query(null, ContentDBInfo.USER + "=?" + " AND " + ContentDBInfo.ID + "= ?", 46 | new String[] { 47 | mUser, String.valueOf(id) 48 | }, null); 49 | if (cursor.moveToFirst()) { 50 | photo = Photo.fromCursor(cursor); 51 | } 52 | cursor.close(); 53 | return photo; 54 | } 55 | 56 | public void bulkInsert(List photos) { 57 | ArrayList contentValues = new ArrayList(); 58 | for (Photo photo : photos) { 59 | ContentValues values = getContentValues(photo); 60 | contentValues.add(values); 61 | } 62 | ContentValues[] valueArray = new ContentValues[contentValues.size()]; 63 | bulkInsert(contentValues.toArray(valueArray)); 64 | } 65 | public static int deleteAllRows(){ 66 | synchronized (DataProvider.DBLock) { 67 | DBHelper mDBHelper = DataProvider.getDBHelper(); 68 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 69 | int row = db.delete(ContentDBInfo.TABLE_NAME, null, null); 70 | return row; 71 | } 72 | } 73 | //只删除某个用户的全部数据 74 | public int deleteAll() { 75 | synchronized (DataProvider.DBLock) { 76 | DBHelper mDBHelper = DataProvider.getDBHelper(); 77 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 78 | int row = db.delete(ContentDBInfo.TABLE_NAME, ContentDBInfo.USER + "=?", new String[] {mUser}); 79 | return row; 80 | } 81 | } 82 | @Override 83 | public CursorLoader getCursorLoader() { 84 | return new CursorLoader(getContext(), getContentUri(), null, ContentDBInfo.USER + "=?", 85 | new String[] {mUser}, ContentDBInfo._ID + " ASC"); 86 | } 87 | 88 | public static final class ContentDBInfo implements BaseColumns { 89 | private ContentDBInfo() { 90 | } 91 | public static final String TABLE_NAME = "useralbum"; 92 | 93 | public static final String ID = "id"; 94 | 95 | public static final String USER = "username"; 96 | 97 | public static final String JSON = "json"; 98 | 99 | public static final SQLiteTable TABLE = new SQLiteTable(TABLE_NAME) 100 | .addColumn(ID, Column.DataType.INTEGER) 101 | .addColumn(USER, Column.DataType.TEXT).addColumn(JSON, Column.DataType.TEXT); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/dao/UserCollectionsDataHelper.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.dao; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.net.Uri; 7 | import android.provider.BaseColumns; 8 | import android.support.v4.content.CursorLoader; 9 | 10 | import com.blackzheng.me.piebald.model.Collection; 11 | import com.blackzheng.me.piebald.util.database.Column; 12 | import com.blackzheng.me.piebald.util.database.SQLiteTable; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by BlackZheng on 2017/2/12. 19 | */ 20 | 21 | public class UserCollectionsDataHelper extends BaseDataHelper{ 22 | 23 | private String mUserId; 24 | 25 | public UserCollectionsDataHelper(Context context, String userId) { 26 | super(context); 27 | mUserId = userId; 28 | } 29 | 30 | @Override 31 | protected Uri getContentUri() { 32 | return DataProvider.USER_COLLECTIONS_URI; 33 | } 34 | 35 | @Override 36 | public CursorLoader getCursorLoader() { 37 | return new CursorLoader(getContext(), getContentUri(), null, ContentDBInfo.USER_ID + "=?", 38 | new String[] { 39 | mUserId 40 | }, ContentDBInfo._ID + " ASC"); 41 | } 42 | 43 | private ContentValues getContentValues(Collection collection) { 44 | ContentValues values = new ContentValues(); 45 | values.put(ContentDBInfo.ID, String.valueOf(collection.id)); 46 | values.put(ContentDBInfo.USER_ID, String.valueOf(collection.user.id)); 47 | values.put(ContentDBInfo.CURATED, collection.curated); 48 | values.put(ContentDBInfo.JSON, collection.toJosn()); 49 | return values; 50 | } 51 | 52 | public void bulkInsert(List collections) { 53 | ArrayList contentValues = new ArrayList(); 54 | for (Collection collection : collections) { 55 | ContentValues values = getContentValues(collection); 56 | contentValues.add(values); 57 | } 58 | ContentValues[] valueArray = new ContentValues[contentValues.size()]; 59 | bulkInsert(contentValues.toArray(valueArray)); 60 | } 61 | 62 | public int deleteAll() { 63 | synchronized (DataProvider.DBLock) { 64 | DBHelper mDBHelper = DataProvider.getDBHelper(); 65 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 66 | int row = db.delete(UserCollectionsDataHelper.ContentDBInfo.TABLE_NAME, ContentDBInfo.USER_ID + "=?", new String[] { 67 | mUserId 68 | }); 69 | return row; 70 | } 71 | } 72 | 73 | /** 74 | * 清空该表格的所有数据,用于清除缓存 75 | * @return 76 | */ 77 | public static int deleteAllRows(){ 78 | synchronized (DataProvider.DBLock) { 79 | DBHelper mDBHelper = DataProvider.getDBHelper(); 80 | SQLiteDatabase db = mDBHelper.getWritableDatabase(); 81 | int row = db.delete(ContentDBInfo.TABLE_NAME, null, null); 82 | return row; 83 | } 84 | } 85 | 86 | public static final class ContentDBInfo implements BaseColumns { 87 | private ContentDBInfo() { 88 | } 89 | 90 | public static final String TABLE_NAME = "user_collections"; 91 | 92 | public static final String ID = "id"; 93 | 94 | public static final String USER_ID = "user_id"; 95 | 96 | public static final String CURATED = "curated"; 97 | 98 | public static final String JSON = "json"; 99 | 100 | public static final SQLiteTable TABLE = new SQLiteTable(TABLE_NAME) 101 | .addColumn(ID, Column.DataType.TEXT).addColumn(USER_ID, Column.DataType.TEXT) 102 | .addColumn(CURATED, Column.DataType.INTEGER).addColumn(JSON, Column.DataType.TEXT); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/data/ImageCacheManager.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.data; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.drawable.BitmapDrawable; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.graphics.drawable.Drawable; 9 | import android.graphics.drawable.LayerDrawable; 10 | import android.view.View; 11 | import android.widget.ImageView; 12 | 13 | 14 | import com.android.volley.DefaultRetryPolicy; 15 | import com.android.volley.Request; 16 | import com.android.volley.RequestQueue; 17 | import com.blackzheng.me.piebald.App; 18 | import com.blackzheng.me.piebald.R; 19 | import com.nostra13.universalimageloader.core.DisplayImageOptions; 20 | import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; 21 | 22 | import net.qiujuer.genius.blur.StackBlur; 23 | 24 | /** 25 | * Created by BlackZheng on 2016/4/7. 26 | */ 27 | public class ImageCacheManager { 28 | 29 | 30 | private ImageCacheManager() { 31 | 32 | } 33 | 34 | public static void loadImage(String url, ImageView imageView, Drawable drawableOnLoading){ 35 | DisplayImageOptions options = new DisplayImageOptions.Builder() 36 | .showImageOnLoading(drawableOnLoading) 37 | .showImageOnFail(R.drawable.error_drawable) 38 | .cacheInMemory(true) 39 | .cacheOnDisk(true) 40 | .bitmapConfig(Bitmap.Config.RGB_565) 41 | .considerExifParams(false) 42 | .build(); 43 | com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(url, imageView, options); 44 | } 45 | 46 | public static void loadImageWithBlur(String url, ImageView imageView, final int defaultColor, final View blurView){ 47 | DisplayImageOptions options = new DisplayImageOptions.Builder() 48 | .showImageOnLoading(defaultColor) 49 | .showImageOnFail(defaultColor) 50 | .cacheInMemory(true) 51 | .cacheOnDisk(true) 52 | .bitmapConfig(Bitmap.Config.RGB_565) 53 | .considerExifParams(false) 54 | .build(); 55 | com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(url, imageView, options, new SimpleImageLoadingListener(){ 56 | @Override 57 | public void onLoadingStarted(String imageUri, View view) { 58 | super.onLoadingStarted(imageUri, view); 59 | blurView.setBackgroundResource(defaultColor); 60 | } 61 | 62 | @Override 63 | public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { 64 | super.onLoadingComplete(imageUri, view, loadedImage); 65 | Drawable[] drawables=new Drawable[2]; 66 | drawables[0] = new BitmapDrawable(null, StackBlur.blurNatively(loadedImage, 20, false)); 67 | drawables[1] = new ColorDrawable(0x55000000); 68 | blurView.setBackground(new LayerDrawable(drawables)); 69 | } 70 | }); 71 | } 72 | 73 | public static void cancelDisplayingTask(ImageView imageView){ 74 | com.nostra13.universalimageloader.core.ImageLoader.getInstance().cancelDisplayTask(imageView); 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.model; 2 | 3 | import com.google.gson.Gson; 4 | 5 | /** 6 | * Created by BlackZheng on 2016/4/4. 7 | */ 8 | public abstract class BaseModel { 9 | public String toJosn(){ 10 | return new Gson().toJson(this); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/model/Collection.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.model; 2 | 3 | import android.database.Cursor; 4 | 5 | import com.blackzheng.me.piebald.dao.CollectionDataHelper; 6 | import com.google.gson.Gson; 7 | 8 | import java.util.HashMap; 9 | 10 | /** 11 | * Created by BlackZheng on 2016/8/27. 12 | */ 13 | public class Collection extends BaseModel { 14 | 15 | private static final HashMap CACHE = new HashMap(); 16 | public int id; 17 | public String title; 18 | public String description; 19 | public String published_at; 20 | public boolean curated; 21 | public int total_photos; 22 | public Photo cover_photo; 23 | public User user; 24 | 25 | public static void addToCache(Collection collection) { 26 | CACHE.put(String.valueOf(collection.id), collection); 27 | } 28 | 29 | public static Collection getFromCache(String id) { 30 | return CACHE.get(id); 31 | } 32 | 33 | public static Collection fromJson(String json) { 34 | return new Gson().fromJson(json, Collection.class); 35 | } 36 | 37 | public static Collection fromCursor(Cursor cursor) { 38 | String id; 39 | try{ 40 | id = cursor.getString(cursor.getColumnIndex(CollectionDataHelper.ContentDBInfo.ID)); 41 | }catch (Exception e){ 42 | String error = cursor.getString(cursor.getColumnIndex(CollectionDataHelper.ContentDBInfo.JSON)); 43 | throw new RuntimeException(error); 44 | } 45 | 46 | Collection collection = getFromCache(id); 47 | if (collection != null) { 48 | return collection; 49 | } 50 | collection = new Gson().fromJson( 51 | cursor.getString(cursor.getColumnIndex(CollectionDataHelper.ContentDBInfo.JSON)), 52 | Collection.class); 53 | addToCache(collection); 54 | return collection; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/model/Feedback.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.model; 2 | 3 | import cn.bmob.v3.BmobObject; 4 | 5 | /** 6 | * Created by BlackZheng on 2016/8/28. 7 | */ 8 | public class Feedback extends BmobObject { 9 | private String subject = "default_subject"; 10 | private String content; 11 | private String model = "default"; 12 | private int sdk_int; 13 | 14 | public String getSubject() { 15 | return subject; 16 | } 17 | 18 | public int getSdk_int() { 19 | return sdk_int; 20 | } 21 | 22 | public String getModel() { 23 | return model; 24 | } 25 | 26 | public String getContent() { 27 | return content; 28 | } 29 | 30 | public void setSubject(String subject) { 31 | this.subject = subject; 32 | } 33 | 34 | public void setSdk_int(int sdk_int) { 35 | this.sdk_int = sdk_int; 36 | } 37 | 38 | public void setModel(String model) { 39 | this.model = model; 40 | } 41 | 42 | public void setContent(String content) { 43 | this.content = content; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/model/Photo.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.model; 2 | 3 | import android.database.Cursor; 4 | 5 | import com.blackzheng.me.piebald.dao.ContentDataHelper; 6 | import com.google.gson.Gson; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | 11 | /** 12 | * Created by BlackZheng on 2016/4/4. 13 | */ 14 | public class Photo extends BaseModel { 15 | 16 | private static final HashMap CACHE = new HashMap(); 17 | 18 | public String id; 19 | public int width; 20 | public int height; 21 | public String color; 22 | public int likes; 23 | public Exif exif; 24 | public Location location; 25 | public Urls urls; 26 | public ArrayList categories; 27 | public Links links; 28 | public User user; 29 | 30 | 31 | 32 | public class Exif{ 33 | public String make; 34 | public String model; 35 | public String exposure_time; 36 | public String aperture; 37 | public String focal_length; 38 | public int iso; 39 | } 40 | public class Location{ 41 | public String city; 42 | public String country; 43 | public Position position; 44 | 45 | public class Position{ 46 | public double latitude; 47 | public double longitude; 48 | } 49 | } 50 | 51 | public class Urls{ 52 | public String raw; 53 | public String full; 54 | public String regular; 55 | public String small; 56 | public String thumb; 57 | } 58 | 59 | public class Category{ 60 | public int id; 61 | public String title; 62 | } 63 | 64 | public class Links{ 65 | public String self; 66 | public String html; 67 | public String download; 68 | } 69 | 70 | public class User{ 71 | public String id; 72 | public String username; 73 | public String name; 74 | public Profile_Image profile_image; 75 | 76 | public class Profile_Image{ 77 | public String small; 78 | public String medium; 79 | public String large; 80 | } 81 | } 82 | 83 | public static void addToCache(Photo photo) { 84 | CACHE.put(photo.id, photo); 85 | } 86 | 87 | public static Photo getFromCache(String id) { 88 | return CACHE.get(id); 89 | } 90 | 91 | public static Photo fromJson(String json) { 92 | return new Gson().fromJson(json, Photo.class); 93 | } 94 | 95 | public static Photo fromCursor(Cursor cursor) { 96 | String id = cursor.getString(cursor.getColumnIndex(ContentDataHelper.ContentDBInfo.ID)); 97 | Photo photo = getFromCache(id); 98 | if (photo != null) { 99 | return photo; 100 | } 101 | photo = new Gson().fromJson( 102 | cursor.getString(cursor.getColumnIndex(ContentDataHelper.ContentDBInfo.JSON)), 103 | Photo.class); 104 | addToCache(photo); 105 | return photo; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/model/User.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.model; 2 | 3 | import android.database.Cursor; 4 | 5 | import com.blackzheng.me.piebald.dao.ContentDataHelper; 6 | import com.blackzheng.me.piebald.dao.UserAlbumDataHelper; 7 | import com.google.gson.Gson; 8 | 9 | import java.util.HashMap; 10 | 11 | /** 12 | * Created by BlackZheng on 2016/8/17. 13 | */ 14 | public class User { 15 | private static final HashMap CACHE = new HashMap(); 16 | 17 | public String id; 18 | public String username; 19 | public String name; 20 | public String portfolio_url; 21 | public String bio; 22 | public String location; 23 | public int total_likes; 24 | public int total_photos; 25 | public int total_collections; 26 | public Profile_Image profile_image; 27 | 28 | public class Profile_Image{ 29 | public String small; 30 | public String medium; 31 | public String large; 32 | } 33 | 34 | public static void addToCache(User user) { 35 | CACHE.put(user.username, user); 36 | } 37 | 38 | public static User getFromCache(String username) { 39 | return CACHE.get(username); 40 | } 41 | 42 | public static User fromJson(String json) { 43 | return new Gson().fromJson(json, User.class); 44 | } 45 | 46 | public static User fromCursor(Cursor cursor) { 47 | String username = cursor.getString(cursor.getColumnIndex(UserAlbumDataHelper.ContentDBInfo.USER)); 48 | User user = getFromCache(username); 49 | if (user != null) { 50 | return user; 51 | } 52 | user = new Gson().fromJson( 53 | cursor.getString(cursor.getColumnIndex(ContentDataHelper.ContentDBInfo.JSON)), 54 | User.class); 55 | addToCache(user); 56 | return user; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.View; 8 | 9 | import com.blackzheng.me.piebald.R; 10 | import com.blackzheng.me.piebald.util.LogHelper; 11 | 12 | public class AboutActivity extends BaseActivity { 13 | private static final String TAG = LogHelper.makeLogTag(AboutActivity.class); 14 | private Toolbar mToolbar; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_about); 20 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 21 | initActionBar(mToolbar); 22 | } 23 | 24 | public void developer(View view){ 25 | Intent intent = new Intent(Intent.ACTION_VIEW); 26 | intent.setData(Uri.parse("http://weibo.com/3557851780")); 27 | startActivity(intent); 28 | } 29 | 30 | public void email(View view){ 31 | // Intent intent=new Intent(Intent.ACTION_SENDTO); 32 | // intent.setData(Uri.parse("mailto:blackzheng22@gmail.com")); 33 | // intent.putExtra(Intent.EXTRA_SUBJECT, "Subject"); 34 | // intent.putExtra(Intent.EXTRA_TEXT, "Text"); 35 | // startActivity(intent); 36 | } 37 | public void github(View view){ 38 | Intent intent = new Intent(Intent.ACTION_VIEW); 39 | intent.setData(Uri.parse("https://github.com/BlackZheng")); 40 | startActivity(intent); 41 | } 42 | public void donate(View view){ 43 | Intent intent = new Intent(Intent.ACTION_VIEW); 44 | intent.setData(Uri.parse("https://qr.alipay.com/apx02931b9d8jlofd8euv47")); 45 | startActivity(intent); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.Message; 9 | import android.preference.PreferenceActivity; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.support.v7.widget.Toolbar; 12 | import android.view.MenuItem; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | 16 | import com.blackzheng.me.piebald.R; 17 | import com.blackzheng.me.piebald.util.ToastUtils; 18 | import com.umeng.analytics.MobclickAgent; 19 | import com.umeng.message.PushAgent; 20 | 21 | import rx.Subscription; 22 | import rx.functions.Action1; 23 | import rx.subscriptions.CompositeSubscription; 24 | import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; 25 | 26 | /** 27 | * Created by BlackZheng on 2016/4/4. 28 | */ 29 | public abstract class BaseActivity extends AppCompatActivity { 30 | 31 | private static final int ERROR_TOAST = 0x321; 32 | public static final Action1 ERRORACTION = new Action1() { 33 | @Override 34 | public void call(Throwable throwable) { 35 | mHandler.sendEmptyMessage(ERROR_TOAST); 36 | } 37 | }; 38 | private static Handler mHandler = new Handler(){ 39 | @Override 40 | public void handleMessage(Message msg) { 41 | switch (msg.what){ 42 | case ERROR_TOAST: 43 | ToastUtils.showLong(R.string.wrong_message); 44 | break; 45 | default: 46 | break; 47 | } 48 | } 49 | }; 50 | private CompositeSubscription mCompositeSubscription; 51 | 52 | protected void addSubscription(Subscription s) { 53 | if (this.mCompositeSubscription == null) { 54 | this.mCompositeSubscription = new CompositeSubscription(); 55 | } 56 | this.mCompositeSubscription.add(s); 57 | } 58 | 59 | public void unsubcrible() { 60 | 61 | if (this.mCompositeSubscription != null) { 62 | this.mCompositeSubscription.unsubscribe(); 63 | } 64 | } 65 | 66 | protected void onCreate(Bundle savedInstanceState) { 67 | super.onCreate(savedInstanceState); 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 69 | Window window = getWindow(); 70 | // Translucent status bar 71 | window.setFlags( 72 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, 73 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 74 | } 75 | PushAgent.getInstance(this).onAppStart(); 76 | 77 | } 78 | 79 | @Override 80 | protected void onResume() { 81 | super.onResume(); 82 | MobclickAgent.onResume(this); 83 | PushAgent.getInstance(this).onAppStart(); 84 | MobclickAgent.onPageStart("SplashScreen"); 85 | } 86 | 87 | @Override 88 | protected void onPause() { 89 | super.onPause(); 90 | MobclickAgent.onPause(this); 91 | } 92 | 93 | protected void initActionBar(Toolbar toolbar) { 94 | setSupportActionBar(toolbar); 95 | getSupportActionBar().setHomeButtonEnabled(true); 96 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 97 | } 98 | 99 | 100 | @Override 101 | public boolean onOptionsItemSelected(MenuItem item) { 102 | switch (item.getItemId()) { 103 | case android.R.id.home: 104 | onBackPressed(); 105 | return true; 106 | case R.id.action_settings: 107 | startActivity(new Intent(this, PreferenceActivity.class)); 108 | return true; 109 | default: 110 | return super.onOptionsItemSelected(item); 111 | } 112 | } 113 | 114 | @Override 115 | protected void onDestroy() { 116 | super.onDestroy(); 117 | unsubcrible(); 118 | } 119 | 120 | @Override 121 | protected void attachBaseContext(Context newBase) { 122 | super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/FeedbackActivity.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui; 2 | 3 | import android.os.Build; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.View; 7 | import android.widget.EditText; 8 | 9 | import com.blackzheng.me.piebald.R; 10 | import com.blackzheng.me.piebald.model.Feedback; 11 | import com.blackzheng.me.piebald.util.LogHelper; 12 | import com.blackzheng.me.piebald.util.ToastUtils; 13 | 14 | import cn.bmob.v3.exception.BmobException; 15 | import cn.bmob.v3.listener.SaveListener; 16 | 17 | public class FeedbackActivity extends BaseActivity { 18 | 19 | private static final String TAG = LogHelper.makeLogTag(FeedbackActivity.class); 20 | private EditText mSubject, mContent; 21 | private Toolbar mToolbar; 22 | private Feedback mFeedback; 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_feedback); 27 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 28 | mSubject = (EditText) findViewById(R.id.subject); 29 | mContent = (EditText) findViewById(R.id.content); 30 | initActionBar(mToolbar); 31 | } 32 | 33 | public void submit(View view){ 34 | String subject = mSubject.getText().toString(); 35 | String content = mContent.getText().toString(); 36 | if(content != null && content.length() > 0){ 37 | mFeedback = new Feedback(); 38 | mFeedback.setModel(Build.MODEL); 39 | mFeedback.setSdk_int(Build.VERSION.SDK_INT); 40 | if(subject != null && content.length() > 0) 41 | mFeedback.setSubject(subject); 42 | mFeedback.setContent(content); 43 | mFeedback.save(new SaveListener() { 44 | @Override 45 | public void done(String s, BmobException e) { 46 | if(e==null){ 47 | ToastUtils.showShort(R.string.feedback_success); 48 | finish(); 49 | }else{ 50 | ToastUtils.showShort(R.string.feedback_fail); 51 | } 52 | } 53 | }); 54 | } 55 | else{ 56 | ToastUtils.showShort(R.string.feedback_null_toast); 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/ShareSelectActivity.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | import com.blackzheng.me.piebald.R; 11 | import com.blackzheng.me.piebald.util.LogHelper; 12 | import com.blackzheng.me.piebald.util.ShareBitmapHolder; 13 | import com.blackzheng.me.piebald.util.ShareImgToWX; 14 | import com.umeng.analytics.MobclickAgent; 15 | 16 | public class ShareSelectActivity extends AppCompatActivity { 17 | 18 | private static final String TAG = LogHelper.makeLogTag(ShareSelectActivity.class); 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | requestWindowFeature(Window.FEATURE_NO_TITLE);//隐藏标题栏 24 | setContentView(R.layout.activity_share_select); 25 | getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT); 26 | getWindow().setGravity(Gravity.BOTTOM); 27 | 28 | 29 | } 30 | public void shareToWeChat(View view){ 31 | MobclickAgent.onEvent(this,"shareToWeChat"); 32 | ShareImgToWX.getInstance().shareToWeChat(ShareBitmapHolder.getmBitmap()); 33 | finish(); 34 | } 35 | public void shareToTimeline(View view){ 36 | MobclickAgent.onEvent(this,"shareToTimeline"); 37 | ShareImgToWX.getInstance().shareToTimeline(ShareBitmapHolder.getmBitmap()); 38 | finish(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/adapter/BaseListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.database.Cursor; 6 | import android.graphics.drawable.Drawable; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.WindowManager; 9 | 10 | /** 11 | * Created by BlackZheng on 2016/8/27. 12 | */ 13 | public abstract class BaseListenerAdapter extends BaseAbstractRecycleCursorAdapter { 14 | private Resources mResource; 15 | private Drawable mDefaultImageDrawable; 16 | private int mWidth; 17 | 18 | public BaseListenerAdapter(Context context, Cursor c) { 19 | super(context, c); 20 | mWidth = ((WindowManager) context 21 | .getSystemService(Context.WINDOW_SERVICE)) 22 | .getDefaultDisplay().getWidth(); 23 | mResource = context.getResources(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/adapter/CursorFilter.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui.adapter; 2 | 3 | import android.database.Cursor; 4 | import android.widget.Filter; 5 | 6 | /** 7 | * Created by BlackZheng on 2016/4/7. 8 | */ 9 | public class CursorFilter extends Filter { 10 | CursorFilterClient mClient; 11 | 12 | interface CursorFilterClient { 13 | CharSequence convertToString(Cursor cursor); 14 | Cursor runQueryOnBackgroundThread(CharSequence constraint); 15 | Cursor getCursor(); 16 | void changeCursor(Cursor cursor); 17 | } 18 | 19 | CursorFilter(CursorFilterClient client) { 20 | mClient = client; 21 | } 22 | 23 | @Override 24 | public CharSequence convertResultToString(Object resultValue) { 25 | return mClient.convertToString((Cursor) resultValue); 26 | } 27 | 28 | @Override 29 | protected FilterResults performFiltering(CharSequence constraint) { 30 | Cursor cursor = mClient.runQueryOnBackgroundThread(constraint); 31 | 32 | FilterResults results = new FilterResults(); 33 | if (cursor != null) { 34 | results.count = cursor.getCount(); 35 | results.values = cursor; 36 | } else { 37 | results.count = 0; 38 | results.values = null; 39 | } 40 | return results; 41 | } 42 | 43 | @Override 44 | protected void publishResults(CharSequence constraint, FilterResults results) { 45 | Cursor oldCursor = mClient.getCursor(); 46 | 47 | if (results.values != null && results.values != oldCursor) { 48 | mClient.changeCursor((Cursor) results.values); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/adapter/UserPhotosAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui.adapter; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.database.Cursor; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.WindowManager; 14 | import android.widget.ImageView; 15 | 16 | import com.blackzheng.me.piebald.R; 17 | import com.blackzheng.me.piebald.data.ImageCacheManager; 18 | import com.blackzheng.me.piebald.model.Photo; 19 | import com.blackzheng.me.piebald.util.Decoder; 20 | import com.blackzheng.me.piebald.util.DrawableUtil; 21 | import com.blackzheng.me.piebald.util.LogHelper; 22 | 23 | import java.util.Random; 24 | 25 | /** 26 | * Created by BlackZheng on 2016/8/17. 27 | */ 28 | public class UserPhotosAdapter extends BaseAbstractRecycleCursorAdapter { 29 | 30 | private static final String TAG = LogHelper.makeLogTag(UserPhotosAdapter.class); 31 | private Resources mResource; 32 | private Drawable mDefaultImageDrawable; 33 | private OnItemClickLitener mOnItemClickLitener; 34 | private int width; 35 | 36 | public UserPhotosAdapter(Context context, Cursor c) { 37 | super(context, c); 38 | width = ((WindowManager) context 39 | .getSystemService(Context.WINDOW_SERVICE)) 40 | .getDefaultDisplay().getWidth() / 2; 41 | mResource = context.getResources(); 42 | } 43 | 44 | @Override 45 | public UserPhotosAdapter.PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 46 | 47 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.album_photo_item, parent, false); 48 | return new PhotoViewHolder(view); 49 | 50 | } 51 | 52 | 53 | @Override 54 | public void onBindViewHolder(final UserPhotosAdapter.PhotoViewHolder holder, Cursor cursor) { 55 | 56 | ImageCacheManager.cancelDisplayingTask(holder.photo); 57 | final Photo photo = Photo.fromCursor(cursor); 58 | if(photo.color != null){ 59 | mDefaultImageDrawable = new ColorDrawable(Color.parseColor(photo.color)); 60 | }else{ 61 | mDefaultImageDrawable = new ColorDrawable(mResource.getColor(DrawableUtil.getDefaultColors()[new Random().nextInt(5)])); 62 | } 63 | 64 | float scale = 1; 65 | //some photo's width may be 0, which will cause FC 66 | if(photo.width != 0){ 67 | scale = (float)photo.height / photo.width; 68 | } 69 | 70 | ViewGroup.LayoutParams lp = holder.photo.getLayoutParams(); 71 | lp.height = (int) (width * scale); 72 | holder.photo.setLayoutParams(lp); 73 | holder.photo.setOnClickListener(new View.OnClickListener() { 74 | @Override 75 | public void onClick(View v) { 76 | int pos = holder.getLayoutPosition(); 77 | mOnItemClickLitener.onItemClick(holder.photo, photo, pos); 78 | } 79 | }); 80 | ImageCacheManager.loadImage(Decoder.decodeURL(photo.urls.thumb), holder.photo, mDefaultImageDrawable); 81 | } 82 | 83 | public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) 84 | { 85 | this.mOnItemClickLitener = mOnItemClickLitener; 86 | } 87 | 88 | public static class PhotoViewHolder extends RecyclerView.ViewHolder { 89 | public ImageView photo; 90 | 91 | public PhotoViewHolder(View itemView) { 92 | super(itemView); 93 | photo = (ImageView) itemView.findViewById(R.id.photo); 94 | } 95 | } 96 | 97 | public interface OnItemClickLitener 98 | { 99 | void onItemClick(View view, Photo photo, int position); 100 | void onItemLongClick(View view , Photo photo, int position); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui.fragment; 2 | 3 | import android.support.v4.app.Fragment; 4 | 5 | import com.blackzheng.me.piebald.R; 6 | import com.blackzheng.me.piebald.util.LogHelper; 7 | import com.blackzheng.me.piebald.util.ToastUtils; 8 | 9 | import rx.Subscription; 10 | import rx.functions.Action1; 11 | import rx.subscriptions.CompositeSubscription; 12 | 13 | /** 14 | * Created by BlackZheng on 2016/4/6. 15 | */ 16 | public abstract class BaseFragment extends Fragment { 17 | 18 | private static final String TAG = LogHelper.makeLogTag(BaseFragment.class); 19 | public static final Action1 ERRORACTION = new Action1() { 20 | @Override 21 | public void call(Throwable throwable) { 22 | ToastUtils.showLong(R.string.wrong_message); 23 | } 24 | }; 25 | 26 | private CompositeSubscription mCompositeSubscription; 27 | 28 | protected void addSubscription(Subscription s) { 29 | if (this.mCompositeSubscription == null) { 30 | this.mCompositeSubscription = new CompositeSubscription(); 31 | } 32 | this.mCompositeSubscription.add(s); 33 | } 34 | 35 | public void unsubcrible() { 36 | 37 | if (this.mCompositeSubscription != null) { 38 | this.mCompositeSubscription.unsubscribe(); 39 | } 40 | } 41 | @Override 42 | public void onDestroy() { 43 | super.onDestroy(); 44 | unsubcrible(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/ui/listener/OnDoubleClickListener.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.ui.listener; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by BlackZheng on 2016/4/24. 7 | */ 8 | public interface OnDoubleClickListener { 9 | public void OnSingleClick(View v); 10 | public void OnDoubleClick(View v); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | 7 | /** 8 | * Created by BlackZheng on 2016/4/26. 9 | */ 10 | public class BitmapUtil { 11 | public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) { 12 | int count = 1; 13 | ByteArrayOutputStream output = new ByteArrayOutputStream(); 14 | // bmp.compress(Bitmap.CompressFormat.PNG, 100, output); 15 | bmp.compress(Bitmap.CompressFormat.JPEG, 100, output);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 16 | int options = 100; 17 | while ( output.toByteArray().length / 1024>32) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 18 | count++; 19 | output.reset();//重置baos即清空baos 20 | bmp.compress(Bitmap.CompressFormat.JPEG, options, output);//这里压缩options%,把压缩后的数据存放到baos中 21 | options -= 10;//每次都减少10 22 | } 23 | if (needRecycle) { 24 | bmp.recycle(); 25 | } 26 | 27 | 28 | byte[] result = output.toByteArray(); 29 | try { 30 | output.close(); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/CacheUtil.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import com.blackzheng.me.piebald.App; 4 | import com.blackzheng.me.piebald.api.UnsplashAPI; 5 | import com.nostra13.universalimageloader.core.ImageLoader; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | /**主要用于获取缓存大小和清除缓存 12 | * Created by BlackZheng on 2016/8/18. 13 | */ 14 | public class CacheUtil { 15 | private static final String TAG = LogHelper.makeLogTag(CacheUtil.class); 16 | public static void clearDiskCache(){ 17 | ImageLoader.getInstance().clearDiskCache(); 18 | } 19 | public static long getDiskCacheSize(){ 20 | return getUILDiskCacheSize(); 21 | } 22 | 23 | private static long getUILDiskCacheSize() { 24 | long size; 25 | try { 26 | size = (int)(getFileSize(ImageLoader.getInstance().getDiskCache().getDirectory())); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | size = 0; 30 | } 31 | return size; 32 | } 33 | 34 | private static long getFileSize(File f)throws Exception //取得文件夹大小 35 | { 36 | long size = 0; 37 | File flist[] = f.listFiles(); 38 | for (int i = 0; i < flist.length; i++) 39 | { 40 | if (flist[i].isDirectory()) 41 | { 42 | size = size + getFileSize(flist[i]); 43 | } else 44 | { 45 | size = size + flist[i].length(); 46 | } 47 | } 48 | return size; 49 | } 50 | 51 | /** 52 | * 递归删除目录下的所有文件及子目录下所有文件 53 | * @param dir 将要删除的文件目录 54 | * @return boolean Returns "true" if all deletions were successful. 55 | * If a deletion fails, the method stops attempting to 56 | * delete and returns "false". 57 | */ 58 | private static boolean deleteDir(File dir) { 59 | if (dir.isDirectory()) { 60 | String[] children = dir.list(); 61 | //递归删除目录中的子目录下 62 | for (int i=0; i MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH) { 18 | return LOG_PREFIX + str.substring(0, MAX_LOG_TAG_LENGTH - LOG_PREFIX_LENGTH - 1); 19 | } 20 | 21 | return LOG_PREFIX + str; 22 | } 23 | 24 | /** 25 | * Don't use this when obfuscating class names! 26 | */ 27 | public static String makeLogTag(Class cls) { 28 | return makeLogTag(cls.getSimpleName()); 29 | } 30 | 31 | 32 | public static void v(String tag, Object... messages) { 33 | // Only log VERBOSE if build type is DEBUG 34 | if (BuildConfig.DEBUG) { 35 | log(tag, Log.VERBOSE, null, messages); 36 | } 37 | } 38 | 39 | public static void d(String tag, Object... messages) { 40 | // Only log DEBUG if build type is DEBUG 41 | if (BuildConfig.DEBUG) { 42 | log(tag, Log.DEBUG, null, messages); 43 | } 44 | } 45 | 46 | public static void i(String tag, Object... messages) { 47 | log(tag, Log.INFO, null, messages); 48 | } 49 | 50 | public static void w(String tag, Object... messages) { 51 | log(tag, Log.WARN, null, messages); 52 | } 53 | 54 | public static void w(String tag, Throwable t, Object... messages) { 55 | log(tag, Log.WARN, t, messages); 56 | } 57 | 58 | public static void e(String tag, Object... messages) { 59 | log(tag, Log.ERROR, null, messages); 60 | } 61 | 62 | public static void e(String tag, Throwable t, Object... messages) { 63 | log(tag, Log.ERROR, t, messages); 64 | } 65 | 66 | public static void log(String tag, int level, Throwable t, Object... messages) { 67 | if (Log.isLoggable(tag, Log.INFO)) { 68 | String message; 69 | if (t == null && messages != null && messages.length == 1) { 70 | // handle this common case without the extra cost of creating a stringbuffer: 71 | message = messages[0].toString(); 72 | } else { 73 | StringBuilder sb = new StringBuilder(); 74 | if (messages != null) for (Object m : messages) { 75 | sb.append(m); 76 | } 77 | if (t != null) { 78 | sb.append("\n").append(Log.getStackTraceString(t)); 79 | } 80 | message = sb.toString(); 81 | } 82 | Log.println(level, tag, message); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | import android.telephony.TelephonyManager; 7 | import android.util.Log; 8 | 9 | /**用于判断用户的网络类型 10 | * Created by BlackZheng on 2016/4/14. 11 | */ 12 | public class NetworkUtils { 13 | private static final String TAG = LogHelper.makeLogTag(NetworkUtils.class); 14 | public static final int NOT_NETWORK = 0x01; 15 | public static final int TYPE_WIFI = 0x02; 16 | public static final int TYPE_MOBILE= 0x03; 17 | public static String strNetworkType; 18 | 19 | public static int getNetworkType(Context ctx) 20 | { 21 | Context context = ctx; 22 | int type = NOT_NETWORK; 23 | 24 | NetworkInfo networkInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); 25 | if (networkInfo != null && networkInfo.isConnected()) 26 | { 27 | if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) 28 | { 29 | type = TYPE_WIFI; 30 | strNetworkType = "WIFI"; 31 | } 32 | else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) 33 | { 34 | String _strSubTypeName = networkInfo.getSubtypeName(); 35 | 36 | LogHelper.d(TAG, "Network getSubtypeName : " + _strSubTypeName); 37 | 38 | // TD-SCDMA networkType is 17 39 | int networkType = networkInfo.getSubtype(); 40 | switch (networkType) { 41 | case TelephonyManager.NETWORK_TYPE_GPRS: 42 | case TelephonyManager.NETWORK_TYPE_EDGE: 43 | case TelephonyManager.NETWORK_TYPE_CDMA: 44 | case TelephonyManager.NETWORK_TYPE_1xRTT: 45 | case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11 46 | type = TYPE_MOBILE; 47 | strNetworkType = "2G"; 48 | break; 49 | case TelephonyManager.NETWORK_TYPE_UMTS: 50 | case TelephonyManager.NETWORK_TYPE_EVDO_0: 51 | case TelephonyManager.NETWORK_TYPE_EVDO_A: 52 | case TelephonyManager.NETWORK_TYPE_HSDPA: 53 | case TelephonyManager.NETWORK_TYPE_HSUPA: 54 | case TelephonyManager.NETWORK_TYPE_HSPA: 55 | case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14 56 | case TelephonyManager.NETWORK_TYPE_EHRPD: //api<11 : replace by 12 57 | case TelephonyManager.NETWORK_TYPE_HSPAP: //api<13 : replace by 15 58 | type = TYPE_MOBILE; 59 | strNetworkType = "3G"; 60 | break; 61 | case TelephonyManager.NETWORK_TYPE_LTE: //api<11 : replace by 13 62 | type = TYPE_MOBILE; 63 | strNetworkType = "4G"; 64 | break; 65 | default: 66 | // http://baike.baidu.com/item/TD-SCDMA 中国移动 联通 电信 三种3G制式 67 | if (_strSubTypeName.equalsIgnoreCase("TD-SCDMA") || _strSubTypeName.equalsIgnoreCase("WCDMA") || _strSubTypeName.equalsIgnoreCase("CDMA2000")) 68 | { 69 | type = TYPE_MOBILE; 70 | strNetworkType = "3G"; 71 | } 72 | else 73 | { 74 | type = TYPE_MOBILE; 75 | strNetworkType = _strSubTypeName; 76 | } 77 | 78 | break; 79 | } 80 | LogHelper.d(TAG, "Network getSubtype : " + Integer.valueOf(networkType).toString()); 81 | } 82 | } 83 | LogHelper.d(TAG, "Network Type : " + strNetworkType); 84 | 85 | return type; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/PathUtils.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | /** 4 | * Created by BlackZheng on 2016/4/16. 5 | */ 6 | public class PathUtils { 7 | //图片下载路径的前缀 8 | public static String path_Prefix = "/storage/emulated/0"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/ResourceUtil.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by BlackZheng on 2016/8/18. 7 | */ 8 | public class ResourceUtil { 9 | public static String getStringFromRes(Context context, int resId){ 10 | return context.getResources().getString(resId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/ShareBitmapHolder.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | /**用于分享图片到微信的过程中bitmap对象的暂存 6 | * Created by BlackZheng on 2016/4/27. 7 | */ 8 | //It holder the bitmap loaded in PhotoZooming Activity for sharing to Wechat 9 | public class ShareBitmapHolder { 10 | private static Bitmap mBitmap; 11 | 12 | public static void setBitmap(Bitmap bmp){ 13 | mBitmap = bmp; 14 | } 15 | public static Bitmap getmBitmap(){ 16 | return mBitmap; 17 | } 18 | public static void recycleBitmap(){ 19 | if(mBitmap != null && !mBitmap.isRecycled()){ 20 | mBitmap.recycle(); 21 | } 22 | mBitmap = null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/ShareImgToWX.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import com.blackzheng.me.piebald.App; 6 | import com.tencent.mm.sdk.modelmsg.SendMessageToWX; 7 | import com.tencent.mm.sdk.modelmsg.WXImageObject; 8 | import com.tencent.mm.sdk.modelmsg.WXMediaMessage; 9 | import com.tencent.mm.sdk.openapi.IWXAPI; 10 | 11 | /**分享到微信的逻辑 12 | * Created by BlackZheng on 2016/4/26. 13 | */ 14 | public class ShareImgToWX { 15 | 16 | private static final int THUMB_SIZE = 150; 17 | private IWXAPI api; 18 | private static ShareImgToWX shareImgToWX; 19 | 20 | private ShareImgToWX(){ 21 | api = App.getWXAPI(); 22 | } 23 | public static ShareImgToWX getInstance(){ 24 | if(shareImgToWX == null){ 25 | shareImgToWX = new ShareImgToWX(); 26 | } 27 | return shareImgToWX; 28 | } 29 | private void share(Bitmap targetbmp, boolean isTimeline){ 30 | Bitmap bmp = targetbmp.copy(targetbmp.getConfig(), false); 31 | 32 | WXImageObject imgObj = new WXImageObject(bmp); 33 | 34 | WXMediaMessage msg = new WXMediaMessage(); 35 | msg.mediaObject = imgObj; 36 | 37 | Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, THUMB_SIZE, THUMB_SIZE * bmp.getHeight()/bmp.getWidth(), true); 38 | bmp.recycle(); 39 | msg.thumbData = BitmapUtil.bmpToByteArray(thumbBmp, true); // ��������ͼ 40 | SendMessageToWX.Req req = new SendMessageToWX.Req(); 41 | req.transaction = buildTransaction("img"); 42 | req.message = msg; 43 | req.scene = isTimeline ? SendMessageToWX.Req.WXSceneTimeline : SendMessageToWX.Req.WXSceneSession; 44 | 45 | api.sendReq(req); 46 | } 47 | private String buildTransaction(final String type) { 48 | return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis(); 49 | } 50 | 51 | public void shareToWeChat(Bitmap bmp){ 52 | share(bmp, false); 53 | } 54 | 55 | public void shareToTimeline(Bitmap bmp){ 56 | share(bmp, true); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | /** 4 | * Created by BlackZheng on 2016/4/25. 5 | */ 6 | public class StringUtil { 7 | 8 | /** 9 | * 缩短EXIF中小数位过多的参数 10 | * @param str 11 | * @return 12 | */ 13 | public static String shortenString(String str) { 14 | if (str.length() > 8) { 15 | return str.substring(0, 7); 16 | } 17 | return str; 18 | } 19 | 20 | /** 21 | * EXIF里的焦距参数有时会带单位mm,有时不会,在这里进行统一 22 | * @param str 23 | * @return 24 | */ 25 | public static String checkFocalLength(String str) { 26 | if (str.endsWith("mm")) { 27 | return str.substring(0, str.length() - 2); 28 | } 29 | return str; 30 | } 31 | 32 | /** 33 | * 服务器返回的日期过长,去掉不需要的时间 34 | * @param date 35 | * @return 36 | */ 37 | public static String dateFormat(String date){ 38 | String format = " " + date.substring(0, date.indexOf('T')); 39 | return format; 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/TaskUtils.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.os.AsyncTask; 4 | import android.os.Build; 5 | 6 | /** 7 | * Created by BlackZheng on 2016/4/7. 8 | */ 9 | public class TaskUtils { 10 | public static void executeAsyncTask( 11 | AsyncTask task, Params... params) { 12 | if (Build.VERSION.SDK_INT >= 11) { 13 | task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 14 | } else { 15 | task.execute(params); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | import com.blackzheng.me.piebald.App; 7 | 8 | /** 9 | * Created by BlackZheng on 2016/4/16. 10 | */ 11 | public class ToastUtils { 12 | private ToastUtils() { 13 | } 14 | 15 | private static void show(Context context, int resId, int duration) { 16 | Toast.makeText(context, resId, duration).show(); 17 | } 18 | 19 | private static void show(Context context, String message, int duration) { 20 | Toast.makeText(context, message, duration).show(); 21 | } 22 | 23 | public static void showShort(int resId) { 24 | Toast.makeText(App.getContext(), resId, Toast.LENGTH_SHORT).show(); 25 | } 26 | 27 | public static void showShort(String message) { 28 | Toast.makeText(App.getContext(), message, Toast.LENGTH_SHORT).show(); 29 | } 30 | 31 | public static void showLong(int resId) { 32 | Toast.makeText(App.getContext(), resId, Toast.LENGTH_LONG).show(); 33 | } 34 | 35 | public static void showLong(String message) { 36 | Toast.makeText(App.getContext(), message, Toast.LENGTH_LONG).show(); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/database/Column.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util.database; 2 | 3 | /** 4 | * Created by BlackZheng on 2016/4/6. 5 | */ 6 | public class Column { 7 | public static enum Constraint { 8 | UNIQUE("UNIQUE"), NOT("NOT"), NULL("NULL"), CHECK("CHECK"), FOREIGN_KEY("FOREIGN KEY"), PRIMARY_KEY( 9 | "PRIMARY KEY"); 10 | 11 | private String value; 12 | 13 | private Constraint(String value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return value; 20 | } 21 | } 22 | 23 | public static enum DataType { 24 | NULL, INTEGER, REAL, TEXT, BLOB 25 | } 26 | 27 | private String mColumnName; 28 | 29 | private Constraint mConstraint; 30 | 31 | private DataType mDataType; 32 | 33 | public Column(String columnName, Constraint constraint, DataType dataType) { 34 | mColumnName = columnName; 35 | mConstraint = constraint; 36 | mDataType = dataType; 37 | } 38 | 39 | public String getColumnName() { 40 | return mColumnName; 41 | } 42 | 43 | public Constraint getConstraint() { 44 | return mConstraint; 45 | } 46 | 47 | public DataType getDataType() { 48 | return mDataType; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/util/database/SQLiteTable.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.util.database; 2 | 3 | import android.database.sqlite.SQLiteDatabase; 4 | import android.provider.BaseColumns; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Created by BlackZheng on 2016/4/6. 10 | */ 11 | public class SQLiteTable { 12 | String mTableName; 13 | 14 | ArrayList mColumnsDefinitions = new ArrayList(); 15 | 16 | public String getTableName() { 17 | return mTableName; 18 | } 19 | 20 | /** 21 | * 会自动添加主键 BaseColumns._ID 22 | * 23 | * @param tableName 24 | */ 25 | public SQLiteTable(String tableName) { 26 | mTableName = tableName; 27 | mColumnsDefinitions.add(new Column(BaseColumns._ID, Column.Constraint.PRIMARY_KEY, 28 | Column.DataType.INTEGER)); 29 | } 30 | 31 | public SQLiteTable addColumn(Column columnsDefinition) { 32 | mColumnsDefinitions.add(columnsDefinition); 33 | return this; 34 | } 35 | 36 | public SQLiteTable addColumn(String columnName, Column.DataType dataType) { 37 | mColumnsDefinitions.add(new Column(columnName, null, dataType)); 38 | return this; 39 | } 40 | 41 | public SQLiteTable addColumn(String columnName, Column.Constraint constraint, 42 | Column.DataType dataType) { 43 | mColumnsDefinitions.add(new Column(columnName, constraint, dataType)); 44 | return this; 45 | } 46 | 47 | public void create(SQLiteDatabase db) { 48 | String formatter = " %s"; 49 | StringBuilder stringBuilder = new StringBuilder(); 50 | stringBuilder.append("CREATE TABLE IF NOT EXISTS "); 51 | stringBuilder.append(mTableName); 52 | stringBuilder.append("("); 53 | int columnCount = mColumnsDefinitions.size(); 54 | int index = 0; 55 | for (Column columnsDefinition : mColumnsDefinitions) { 56 | stringBuilder.append(columnsDefinition.getColumnName()).append( 57 | String.format(formatter, columnsDefinition.getDataType().name())); 58 | Column.Constraint constraint = columnsDefinition.getConstraint(); 59 | 60 | if (constraint != null) { 61 | stringBuilder.append(String.format(formatter, constraint.toString())); 62 | } 63 | if (index < columnCount - 1) { 64 | stringBuilder.append(","); 65 | } 66 | index++; 67 | } 68 | stringBuilder.append(");"); 69 | db.execSQL(stringBuilder.toString()); 70 | } 71 | 72 | public void delete(final SQLiteDatabase db) { 73 | db.execSQL("DROP TABLE IF EXISTS " + mTableName); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/blackzheng/me/piebald/view/HideableToolbar.java: -------------------------------------------------------------------------------- 1 | package com.blackzheng.me.piebald.view; 2 | 3 | import android.animation.ObjectAnimator; 4 | import android.content.Context; 5 | import android.support.v7.widget.Toolbar; 6 | import android.util.AttributeSet; 7 | import android.view.animation.AccelerateInterpolator; 8 | 9 | /** 10 | * Created by BlackZheng on 2016/4/27. 11 | */ 12 | public class HideableToolbar extends Toolbar { 13 | 14 | ObjectAnimator animator; 15 | 16 | public HideableToolbar(Context context, AttributeSet attrs) { super(context, attrs); } 17 | private ObjectAnimator getAnimator(int translationY){ 18 | animator = ObjectAnimator.ofFloat(this, "translationY", translationY); 19 | animator.setInterpolator(new AccelerateInterpolator()); 20 | animator.setDuration(100); 21 | return animator; 22 | } 23 | public void hide(){ 24 | getAnimator(-getHeight()).start(); 25 | } 26 | public void show(){ 27 | getAnimator(0).start(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_from_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_from_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_to_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 23 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_thin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/default_profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/default_profile.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/dissatisfied.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/dissatisfied.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/error_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/like.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/moments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/moments.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/noti_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/noti_small.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/profile.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/shade.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlackZheng/Piebald/d52663310cff16d13a5b7c32874901e17ca9c905/app/src/main/res/drawable/wechat.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_collection.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 22 | 27 | 36 | 39 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_feedback.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 18 | 29 |