`
yanguz123
  • 浏览: 568060 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

oschina android app 2.2.1 源码收藏

 
阅读更多
package net.oschina.app.ui;

import java.lang.ref.WeakReference;

import net.oschina.app.R;
import net.oschina.app.base.BaseActivity;
import net.oschina.app.base.BaseFragment;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.emoji.OnSendClickListener;
import net.oschina.app.fragment.MessageDetailFragment;
import net.oschina.app.fragment.TweetPubFragment;
import net.oschina.app.fragment.TweetsFragment;
import net.oschina.app.util.UIHelper;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class SimpleBackActivity extends BaseActivity implements
        OnSendClickListener {

    public final static String BUNDLE_KEY_PAGE = "BUNDLE_KEY_PAGE";
    public final static String BUNDLE_KEY_ARGS = "BUNDLE_KEY_ARGS";
    private static final String TAG = "FLAG_TAG";
    protected WeakReference<Fragment> mFragment;
    protected int mPageValue = -1;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_simple_fragment;
    }

    @Override
    protected boolean hasBackButton() {
        return true;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        super.init(savedInstanceState);
        if (mPageValue == -1) {
            mPageValue = getIntent().getIntExtra(BUNDLE_KEY_PAGE, 0);
        }
        initFromIntent(mPageValue, getIntent());
    }

    protected void initFromIntent(int pageValue, Intent data) {
        if (data == null) {
            throw new RuntimeException(
                    "you must provide a page info to display");
        }
        SimpleBackPage page = SimpleBackPage.getPageByValue(pageValue);
        if (page == null) {
            throw new IllegalArgumentException("can not find page by value:"
                    + pageValue);
        }

        setActionBarTitle(page.getTitle());

        try {
            Fragment fragment = (Fragment) page.getClz().newInstance();

            Bundle args = data.getBundleExtra(BUNDLE_KEY_ARGS);
            if (args != null) {
                fragment.setArguments(args);
            }

            FragmentTransaction trans = getSupportFragmentManager()
                    .beginTransaction();
            trans.replace(R.id.container, fragment, TAG);
            trans.commitAllowingStateLoss();

            mFragment = new WeakReference<Fragment>(fragment);
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException(
                    "generate fragment error. by value:" + pageValue);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mFragment.get() instanceof TweetsFragment) {
            setActionBarTitle("话题");
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.public_menu_send:
            if (mFragment.get() instanceof TweetsFragment) {
                sendTopic();
            } else {
                return super.onOptionsItemSelected(item);
            }
            break;
        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (mFragment.get() instanceof TweetsFragment) {
            getMenuInflater().inflate(R.menu.pub_topic_menu, menu);
        }
        return super.onCreateOptionsMenu(menu);
    }

    /**
     * 发送话题
     */
    private void sendTopic() {
        Bundle bundle = new Bundle();
        bundle.putInt(TweetPubFragment.ACTION_TYPE,
                TweetPubFragment.ACTION_TYPE_TOPIC);
        bundle.putString("tweet_topic", "#"
                + ((TweetsFragment) mFragment.get()).getTopic() + "# ");
        UIHelper.showTweetActivity(this, SimpleBackPage.TWEET_PUB, bundle);
    }

    @Override
    public void onBackPressed() {
        if (mFragment != null && mFragment.get() != null
                && mFragment.get() instanceof BaseFragment) {
            BaseFragment bf = (BaseFragment) mFragment.get();
            if (!bf.onBackPressed()) {
                super.onBackPressed();
            }
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.ACTION_DOWN
                && mFragment.get() instanceof BaseFragment) {
            ((BaseFragment) mFragment.get()).onBackPressed();
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onActivityResult(int arg0, int arg1, Intent arg2) {
        super.onActivityResult(arg0, arg1, arg2);
    }

    @Override
    public void onClick(View v) {}

    @Override
    public void initView() {}

    @Override
    public void initData() {}

    @Override
    public void onClickSendButton(Editable str) {
        if (mFragment.get() instanceof MessageDetailFragment) {
            ((OnSendClickListener) mFragment.get()).onClickSendButton(str);
            ((MessageDetailFragment) mFragment.get()).emojiFragment.clean();
        }
    }

    @Override
    public void onClickFlagButton() {}
}

 

 

AndroidManifest.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.oschina.app"
    android:versionCode="44"
    android:versionName="2.2.1" >

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="20" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RESTART_PACKAGES" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <application
        android:name=".AppContext"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/ActionBarBaseTheme" >
        <activity
            android:name=".AppStart"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.AppStartLoad" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ui.MainActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="www.oschina.net"
                    android:scheme="http" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="www.oschina.net"
                    android:scheme="https" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="my.oschina.net"
                    android:scheme="http" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />

                <data
                    android:host="my.oschina.net"
                    android:scheme="https" />
            </intent-filter>
        </activity>
        <activity
            android:name="net.oschina.app.ui.TweetActivity"
            android:label="发送到动弹"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.SEND" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>
        <activity android:name=".ui.EventLocationActivity" />
        <activity
            android:name=".ui.LoginActivity"
            android:configChanges="keyboardHidden|orientation"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name=".ui.DetailActivity"
            android:configChanges="keyboardHidden|orientation"
            android:screenOrientation="portrait"
            android:theme="@style/ActionBarBaseTheme"
            android:windowSoftInputMode="stateHidden|adjustResize" />
        <activity
            android:name=".ui.ImagePreviewActivity"
            android:configChanges="keyboardHidden|orientation"
            android:screenOrientation="portrait" />
        <activity
            android:name=".ui.SimpleBackActivity"
            android:configChanges="keyboardHidden|orientation"
            android:screenOrientation="portrait" />
        <activity
            android:name=".team.ui.TeamMainActivity"
            android:screenOrientation="portrait" />
        <activity
            android:name=".team.ui.TeamNewActiveActivity"
            android:configChanges="keyboardHidden|orientation"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize" />
        <activity
            android:name="com.dtr.zxing.activity.CaptureActivity"
            android:label="@string/actionbar_title_qr_scan"
            android:screenOrientation="portrait" >
        </activity>

        <service android:name="net.oschina.app.LogUploadService" />

        <!-- ############ QQ空间和QQ SSO授权的Activity注册 ############ -->
        <activity
            android:name="com.tencent.tauth.AuthActivity"
            android:launchMode="singleTask"
            android:noHistory="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- 100424468,如果你使用的公用账号,则不需要修改;否则修改成你在QQ开放平台申请的 APP ID -->
                <data android:scheme="tencent100424468" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.tencent.connect.common.AssistActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" >
        </activity>

        <service android:name="net.oschina.app.service.ServerTaskService" >
            <intent-filter>
                <action android:name="net.oschina.app.ACTION_PUB_BLOG_COMMENT" />
            </intent-filter>
            <intent-filter>
                <action android:name="net.oschina.app.ACTION_PUB_COMMENT" />
            </intent-filter>
            <intent-filter>
                <action android:name="net.oschina.app.ACTION_PUB_POST" />
            </intent-filter>
            <intent-filter>
                <action android:name="net.oschina.app.ACTION_PUB_TWEET" />
            </intent-filter>
            <intent-filter>
                <action android:name="net.oschina.app.ACTION_PUB_SOFTWARE_TWEET" />
            </intent-filter>
        </service>

        <receiver android:name="net.oschina.app.broadcast.AlarmReceiver" />

        <service
            android:name="net.oschina.app.service.NoticeService"
            android:process=":notice" />
        <service android:name="net.oschina.app.service.DownloadService" />

        <meta-data
            android:name="UMENG_APPKEY"
            android:value="53cb520c56240bbd7d076ce5" >
        </meta-data>
        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="channel_beta" >
        </meta-data>
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="pIbgtjFevz8LlkbNsYUNl4Qp" />

        <service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
        </service>

        <activity
            android:name="com.tencent.tauth.AuthActivity"
            android:launchMode="singleTask"
            android:noHistory="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="tencent100942993" />
            </intent-filter>
        </activity>
        
        <activity
            android:name="com.tencent.connect.common.AssistActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
    </application>

</manifest>

 

 

 

 

proguard-project.txt 文件

# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}
-libraryjars /libs/android-async-http-1.4.6.jar
-libraryjars /libs/android-support-v4.jar
-libraryjars /libs/baidumapapi_v3_2_0.jar
-libraryjars /libs/butterknife-5.1.2.jar
-libraryjars /libs/core-2.3.0.jar
-libraryjars /libs/KJFrameForAndroid_V2.03.jar
-libraryjars /libs/locSDK_3.1.jar
-libraryjars /libs/universal-image-loader-1.9.3.jar
-libraryjars /libs/xstream-1.4.7.jar

-dontwarn butterknife.**
-dontwarn com.tencent.**
-dontwarn com.thoughtworks.xstream.**
-dontwarn com.baidu.**

-keep class com.baidu.** { *; }
-keep class vi.com.gdi.bgl.android.**{*;} 
-keep class android.support.v4.** {*; }
-keep class com.tencent.connect.** {*;}

#友盟
-dontshrink
-dontoptimize
-dontwarn com.google.android.maps.**
-dontwarn android.webkit.WebView
-dontwarn com.umeng.**
-dontwarn com.tencent.weibo.sdk.**
-dontwarn com.facebook.**

-keep enum com.facebook.**
-keepattributes Exceptions,InnerClasses,Signature
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable

-keep public interface com.facebook.**
-keep public interface com.tencent.**
-keep public interface com.umeng.socialize.**
-keep public interface com.umeng.socialize.sensor.**
-keep public interface com.umeng.scrshot.**

-keep public class com.umeng.socialize.* {*;}
-keep public class javax.**
-keep public class android.webkit.**

-keep class com.facebook.**
-keep class com.umeng.scrshot.**
-keep public class com.tencent.** {*;}
-keep class com.umeng.socialize.sensor.**

-keep class com.tencent.mm.sdk.modelmsg.WXMediaMessage {*;}

-keep class com.tencent.mm.sdk.modelmsg.** implements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;}

-keep class im.yixin.sdk.api.YXMessage {*;}
-keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}

-keep public class [your_pkg].R$*{
    public static final int *;
}

 

 

 

 

project.properties

# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-20
android.library.reference.1=../osc-android-app-appcompat-v7
android.library.reference.2=../libraries/UmengShareLib
android.library.reference.3=../libraries/PhotoView-library

 

 

 

 

 

lint.xml

<?xml version="1.0" encoding="UTF-8"?>
<lint>
    <issue id="AaptCrash" severity="ignore" />
    <issue id="AccidentalOctal" severity="ignore" />
    <issue id="AdapterViewChildren" severity="ignore" />
    <issue id="AddJavascriptInterface" severity="ignore" />
    <issue id="AllowBackup" severity="ignore" />
    <issue id="AlwaysShowAction" severity="ignore" />
    <issue id="AndroidGradlePluginVersion" severity="ignore" />
    <issue id="AppCompatMethod" severity="ignore" />
    <issue id="AppCompatResource" severity="ignore" />
    <issue id="Assert" severity="ignore" />
    <issue id="ButtonCase" severity="ignore" />
    <issue id="ButtonOrder" severity="ignore" />
    <issue id="ButtonStyle" severity="ignore" />
    <issue id="ByteOrderMark" severity="ignore" />
    <issue id="ClickableViewAccessibility" severity="ignore" />
    <issue id="CommitPrefEdits" severity="ignore" />
    <issue id="CommitTransaction" severity="ignore" />
    <issue id="ContentDescription" severity="ignore" />
    <issue id="CutPasteId" severity="ignore" />
    <issue id="DalvikOverride" severity="ignore" />
    <issue id="DefaultLocale" severity="ignore" />
    <issue id="Deprecated" severity="ignore" />
    <issue id="DeviceAdmin" severity="ignore" />
    <issue id="DisableBaselineAlignment" severity="ignore" />
    <issue id="DrawAllocation" severity="ignore" />
    <issue id="DuplicateActivity" severity="ignore" />
    <issue id="DuplicateDefinition" severity="ignore" />
    <issue id="DuplicateIds" severity="ignore" />
    <issue id="DuplicateIncludedIds" severity="ignore" />
    <issue id="DuplicateUsesFeature" severity="ignore" />
    <issue id="EnforceUTF8" severity="ignore" />
    <issue id="ExportedContentProvider" severity="ignore" />
    <issue id="ExportedPreferenceActivity" severity="ignore" />
    <issue id="ExportedReceiver" severity="ignore" />
    <issue id="ExportedService" severity="ignore" />
    <issue id="ExtraText" severity="ignore" />
    <issue id="ExtraTranslation" severity="ignore" />
    <issue id="FloatMath" severity="ignore" />
    <issue id="GetInstance" severity="ignore" />
    <issue id="GifUsage" severity="ignore" />
    <issue id="GradleCompatible" severity="ignore" />
    <issue id="GradleDependency" severity="ignore" />
    <issue id="GradleDeprecated" severity="ignore" />
    <issue id="GradleGetter" severity="ignore" />
    <issue id="GradleIdeError" severity="ignore" />
    <issue id="GradleOverrides" severity="ignore" />
    <issue id="GradlePath" severity="ignore" />
    <issue id="GrantAllUris" severity="ignore" />
    <issue id="GridLayout" severity="ignore" />
    <issue id="HandlerLeak" severity="ignore" />
    <issue id="HardcodedDebugMode" severity="ignore" />
    <issue id="HardcodedText" severity="ignore" />
    <issue id="IconColors" severity="ignore" />
    <issue id="IconDensities" severity="ignore" />
    <issue id="IconDipSize" severity="ignore" />
    <issue id="IconDuplicates" severity="ignore" />
    <issue id="IconDuplicatesConfig" severity="ignore" />
    <issue id="IconExtension" severity="ignore" />
    <issue id="IconLauncherShape" severity="ignore" />
    <issue id="IconLocation" severity="ignore" />
    <issue id="IconMissingDensityFolder" severity="ignore" />
    <issue id="IconMixedNinePatch" severity="ignore" />
    <issue id="IconNoDpi" severity="ignore" />
    <issue id="IconXmlAndPng" severity="ignore" />
    <issue id="IllegalResourceRef" severity="ignore" />
    <issue id="ImpliedQuantity" severity="ignore" />
    <issue id="ImproperProjectLevelStatement" severity="ignore" />
    <issue id="InOrMmUsage" severity="ignore" />
    <issue id="IncludeLayoutParam" severity="ignore" />
    <issue id="InconsistentArrays" severity="ignore" />
    <issue id="InconsistentLayout" severity="ignore" />
    <issue id="InefficientWeight" severity="ignore" />
    <issue id="InflateParams" severity="ignore" />
    <issue id="InlinedApi" severity="ignore" />
    <issue id="InnerclassSeparator" severity="ignore" />
    <issue id="Instantiatable" severity="ignore" />
    <issue id="InvalidId" severity="ignore" />
    <issue id="InvalidPackage" severity="ignore" />
    <issue id="JavascriptInterface" severity="ignore" />
    <issue id="LabelFor" severity="ignore" />
    <issue id="LibraryCustomView" severity="ignore" />
    <issue id="LocalSuppress" severity="ignore" />
    <issue id="LocaleFolder" severity="ignore" />
    <issue id="MangledCRLF" severity="ignore" />
    <issue id="ManifestOrder" severity="ignore" />
    <issue id="ManifestTypo" severity="ignore" />
    <issue id="MenuTitle" severity="ignore" />
    <issue id="MergeRootFrame" severity="ignore" />
    <issue id="MisplacedStatement" severity="ignore" />
    <issue id="MissingApplicationIcon" severity="ignore" />
    <issue id="MissingId" severity="ignore" />
    <issue id="MissingPrefix" severity="ignore" />
    <issue id="MissingQuantity" severity="ignore" />
    <issue id="MissingRegistered" severity="ignore" />
    <issue id="MissingSuperCall" severity="ignore" />
    <issue id="MissingTranslation" severity="ignore" />
    <issue id="MissingVersion" severity="ignore" />
    <issue id="MockLocation" severity="ignore" />
    <issue id="MultipleUsesSdk" severity="ignore" />
    <issue id="NamespaceTypo" severity="ignore" />
    <issue id="NestedScrolling" severity="ignore" />
    <issue id="NestedWeights" severity="ignore" />
    <issue id="NewApi" severity="ignore" />
    <issue id="NfcTechWhitespace" severity="ignore" />
    <issue id="NotSibling" severity="ignore" />
    <issue id="ObsoleteLayoutParam" severity="ignore" />
    <issue id="OldTargetApi" severity="ignore" />
    <issue id="OnClick" severity="ignore" />
    <issue id="Orientation" severity="ignore" />
    <issue id="Overdraw" severity="ignore" />
    <issue id="Override" severity="ignore" />
    <issue id="PackagedPrivateKey" severity="ignore" />
    <issue id="ParcelCreator" severity="ignore" />
    <issue id="PrivateResource" severity="ignore" />
    <issue id="Proguard" severity="ignore" />
    <issue id="ProguardSplit" severity="ignore" />
    <issue id="PropertyEscape" severity="ignore" />
    <issue id="ProtectedPermissions" severity="ignore" />
    <issue id="PxUsage" severity="ignore" />
    <issue id="Recycle" severity="ignore" />
    <issue id="ReferenceType" severity="ignore" />
    <issue id="Registered" severity="ignore" />
    <issue id="RequiredSize" severity="ignore" />
    <issue id="ResAuto" severity="ignore" />
    <issue id="ResourceAsColor" severity="ignore" />
    <issue id="ResourceCycle" severity="ignore" />
    <issue id="ResourceName" severity="ignore" />
    <issue id="ScrollViewCount" severity="ignore" />
    <issue id="ScrollViewSize" severity="ignore" />
    <issue id="SdCardPath" severity="ignore" />
    <issue id="SecureRandom" severity="ignore" />
    <issue id="ServiceCast" severity="ignore" />
    <issue id="SetJavaScriptEnabled" severity="ignore" />
    <issue id="ShowToast" severity="ignore" />
    <issue id="SignatureOrSystemPermissions" severity="ignore" />
    <issue id="SimpleDateFormat" severity="ignore" />
    <issue id="SmallSp" severity="ignore" />
    <issue id="SpUsage" severity="ignore" />
    <issue id="StateListReachable" severity="ignore" />
    <issue id="StringFormatCount" severity="ignore" />
    <issue id="StringFormatInvalid" severity="ignore" />
    <issue id="StringFormatMatches" severity="ignore" />
    <issue id="StringShouldBeInt" severity="ignore" />
    <issue id="Suspicious0dp" severity="ignore" />
    <issue id="SuspiciousImport" severity="ignore" />
    <issue id="TextFields" severity="ignore" />
    <issue id="TextViewEdits" severity="ignore" />
    <issue id="TooDeepLayout" severity="ignore" />
    <issue id="TooManyViews" severity="ignore" />
    <issue id="TrulyRandom" severity="ignore" />
    <issue id="TypographyDashes" severity="ignore" />
    <issue id="TypographyEllipsis" severity="ignore" />
    <issue id="TypographyFractions" severity="ignore" />
    <issue id="TypographyOther" severity="ignore" />
    <issue id="Typos" severity="ignore" />
    <issue id="UniquePermission" severity="ignore" />
    <issue id="UnknownId" severity="ignore" />
    <issue id="UnknownIdInLayout" severity="ignore" />
    <issue id="UnlocalizedSms" severity="ignore" />
    <issue id="UnusedAttribute" severity="ignore" />
    <issue id="UnusedNamespace" severity="ignore" />
    <issue id="UnusedQuantity" severity="ignore" />
    <issue id="UnusedResources" severity="ignore" />
    <issue id="UseCheckPermission" severity="ignore" />
    <issue id="UseCompoundDrawables" severity="ignore" />
    <issue id="UseSparseArrays" severity="ignore" />
    <issue id="UseValueOf" severity="ignore" />
    <issue id="UselessLeaf" severity="ignore" />
    <issue id="UselessParent" severity="ignore" />
    <issue id="UsesMinSdkAttributes" severity="ignore" />
    <issue id="ValidFragment" severity="ignore" />
    <issue id="ViewConstructor" severity="ignore" />
    <issue id="ViewHolder" severity="ignore" />
    <issue id="ViewTag" severity="ignore" />
    <issue id="Wakelock" severity="ignore" />
    <issue id="WebViewLayout" severity="ignore" />
    <issue id="WorldReadableFiles" severity="ignore" />
    <issue id="WorldWriteableFiles" severity="ignore" />
    <issue id="WrongCall" severity="ignore" />
    <issue id="WrongCase" severity="ignore" />
    <issue id="WrongFolder" severity="ignore" />
    <issue id="WrongManifestParent" severity="ignore" />
    <issue id="WrongViewCast" severity="ignore" />
</lint>

 

 

 

 

 

 

 

BaseApplication.java

package net.oschina.app.base;

import net.oschina.app.R;
import net.oschina.app.util.StringUtils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint("InflateParams")
public class BaseApplication extends Application {
    private static String PREF_NAME = "creativelocker.pref";
    private static String LAST_REFRESH_TIME = "last_refresh_time.pref";
    static Context _context;
    static Resources _resource;
    private static String lastToast = "";
    private static long lastToastTime;

    private static boolean sIsAtLeastGB;

    static {
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
	    sIsAtLeastGB = true;
	}
    }

    @Override
    public void onCreate() {
	super.onCreate();
	_context = getApplicationContext();
	_resource = _context.getResources();
    }

    public static synchronized BaseApplication context() {
	return (BaseApplication) _context;
    }

    public static Resources resources() {
	return _resource;
    }

    /**
     * 放入已读文章列表中
     * 
     * @param id
     */
    public static void putReadedPostList(String prefFileName, String key,
	    String value) {
	SharedPreferences preferences = getPreferences(prefFileName);
	int size = preferences.getAll().size();
	Editor editor = preferences.edit();
	if (size >= 100) {
	    editor.clear();
	}
	editor.putString(key, value);
	apply(editor);
    }
    
    /**
     * 读取是否是已读的文章列表
     * 
     * @param id
     * @return
     */
    public static boolean isOnReadedPostList(String prefFileName, String key) {
	return getPreferences(prefFileName).contains(key);
    }
    
    /***
     * 记录列表上次刷新时间
     * @author 火蚁
     * 2015-2-9 下午2:21:37
     *
     * @return void
     * @param key
     * @param value
     */
    public static void putToLastRefreshTime(String key, String value) {
	SharedPreferences preferences = getPreferences(LAST_REFRESH_TIME);
	Editor editor = preferences.edit();
	editor.putString(key, value);
	apply(editor);
    }
    
    /***
     * 获取列表的上次刷新时间
     * @author 火蚁
     * 2015-2-9 下午2:22:04
     *
     * @return String
     * @param key
     * @return
     */
    public static String getLastRefreshTime(String key) {
	return getPreferences(LAST_REFRESH_TIME).getString(key, StringUtils.getCurTimeStr());
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    public static void apply(SharedPreferences.Editor editor) {
	if (sIsAtLeastGB) {
	    editor.apply();
	} else {
	    editor.commit();
	}
    }

    public static void set(String key, boolean value) {
	Editor editor = getPreferences().edit();
	editor.putBoolean(key, value);
	apply(editor);
    }

    public static void set(String key, String value) {
	Editor editor = getPreferences().edit();
	editor.putString(key, value);
	apply(editor);
    }

    public static boolean get(String key, boolean defValue) {
	return getPreferences().getBoolean(key, defValue);
    }

    public static String get(String key, String defValue) {
	return getPreferences().getString(key, defValue);
    }

    public static int get(String key, int defValue) {
	return getPreferences().getInt(key, defValue);
    }

    public static long get(String key, long defValue) {
	return getPreferences().getLong(key, defValue);
    }

    public static float get(String key, float defValue) {
	return getPreferences().getFloat(key, defValue);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static SharedPreferences getPreferences() {
	SharedPreferences pre = context().getSharedPreferences(PREF_NAME,
		Context.MODE_MULTI_PROCESS);
	return pre;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static SharedPreferences getPreferences(String prefName) {
	return context().getSharedPreferences(prefName,
		Context.MODE_MULTI_PROCESS);
    }

    public static int[] getDisplaySize() {
	return new int[] { getPreferences().getInt("screen_width", 480),
		getPreferences().getInt("screen_height", 854) };
    }

    public static void saveDisplaySize(Activity activity) {
	DisplayMetrics displaymetrics = new DisplayMetrics();
	activity.getWindowManager().getDefaultDisplay()
		.getMetrics(displaymetrics);
	SharedPreferences.Editor editor = getPreferences().edit();
	editor.putInt("screen_width", displaymetrics.widthPixels);
	editor.putInt("screen_height", displaymetrics.heightPixels);
	editor.putFloat("density", displaymetrics.density);
	editor.commit();
    }

    public static String string(int id) {
	return _resource.getString(id);
    }

    public static String string(int id, Object... args) {
	return _resource.getString(id, args);
    }

    public static void showToast(int message) {
	showToast(message, Toast.LENGTH_LONG, 0);
    }

    public static void showToast(String message) {
	showToast(message, Toast.LENGTH_LONG, 0, Gravity.BOTTOM);
    }

    public static void showToast(int message, int icon) {
	showToast(message, Toast.LENGTH_LONG, icon);
    }

    public static void showToast(String message, int icon) {
	showToast(message, Toast.LENGTH_LONG, icon, Gravity.BOTTOM);
    }

    public static void showToastShort(int message) {
	showToast(message, Toast.LENGTH_SHORT, 0);
    }

    public static void showToastShort(String message) {
	showToast(message, Toast.LENGTH_SHORT, 0, Gravity.BOTTOM);
    }

    public static void showToastShort(int message, Object... args) {
	showToast(message, Toast.LENGTH_SHORT, 0, Gravity.BOTTOM, args);
    }

    public static void showToast(int message, int duration, int icon) {
	showToast(message, duration, icon, Gravity.BOTTOM);
    }

    public static void showToast(int message, int duration, int icon,
	    int gravity) {
	showToast(context().getString(message), duration, icon, gravity);
    }

    public static void showToast(int message, int duration, int icon,
	    int gravity, Object... args) {
	showToast(context().getString(message, args), duration, icon, gravity);
    }

    public static void showToast(String message, int duration, int icon,
	    int gravity) {
	if (message != null && !message.equalsIgnoreCase("")) {
	    long time = System.currentTimeMillis();
	    if (!message.equalsIgnoreCase(lastToast)
		    || Math.abs(time - lastToastTime) > 2000) {
		View view = LayoutInflater.from(context()).inflate(
			R.layout.view_toast, null);
		((TextView) view.findViewById(R.id.title_tv)).setText(message);
		if (icon != 0) {
		    ((ImageView) view.findViewById(R.id.icon_iv))
			    .setImageResource(icon);
		    ((ImageView) view.findViewById(R.id.icon_iv))
			    .setVisibility(View.VISIBLE);
		}
		Toast toast = new Toast(context());
		toast.setView(view);
		if (gravity == Gravity.CENTER) {
		    toast.setGravity(gravity, 0, 0);
		} else {
		    toast.setGravity(gravity, 0, 35);
		}

		toast.setDuration(duration);
		toast.show();
		lastToast = message;
		lastToastTime = System.currentTimeMillis();
	    }
	}
    }
}

 

 

 

 

 

 

 

BaseActivity.java

package net.oschina.app.base;

import net.oschina.app.AppManager;
import net.oschina.app.R;
import net.oschina.app.interf.BaseViewInterface;
import net.oschina.app.ui.dialog.CommonToast;
import net.oschina.app.ui.dialog.DialogControl;
import net.oschina.app.ui.dialog.DialogHelper;
import net.oschina.app.ui.dialog.WaitDialog;
import net.oschina.app.util.TDevice;

import org.kymjs.kjframe.utils.StringUtils;

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.LayoutParams;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Spinner;
import android.widget.TextView;
import butterknife.ButterKnife;

/**
 * baseActionBar Activity
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年9月25日 上午11:30:15 引用自:tonlin
 */
public abstract class BaseActivity extends ActionBarActivity implements
        DialogControl, View.OnClickListener, BaseViewInterface {
    public static final String INTENT_ACTION_EXIT_APP = "INTENT_ACTION_EXIT_APP";

    private boolean _isVisible;
    private WaitDialog _waitDialog;

    protected LayoutInflater mInflater;
    protected ActionBar mActionBar;
    private TextView mTvActionTitle;

    @Override
    protected void onDestroy() {
        super.onDestroy();
        TDevice.hideSoftKeyboard(getCurrentFocus());
        ButterKnife.reset(this);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppManager.getAppManager().addActivity(this);
        if (!hasActionBar()) {
            // supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        }
        onBeforeSetContentLayout();
        if (getLayoutId() != 0) {
            setContentView(getLayoutId());
        }
        mActionBar = getSupportActionBar();
        mInflater = getLayoutInflater();
        if (hasActionBar()) {
            initActionBar(mActionBar);
        }

        // 通过注解绑定控件
        ButterKnife.inject(this);

        init(savedInstanceState);
        initView();
        initData();
        _isVisible = true;
    }

    protected void onBeforeSetContentLayout() {}

    protected boolean hasActionBar() {
        return true;
    }

    protected int getLayoutId() {
        return 0;
    }

    protected View inflateView(int resId) {
        return mInflater.inflate(resId, null);
    }

    protected int getActionBarTitle() {
        return R.string.app_name;
    }

    protected boolean hasBackButton() {
        return false;
    }

    protected int getActionBarCustomView() {
        return 0;
    }

    protected boolean haveSpinner() {
        return false;
    }

    protected void init(Bundle savedInstanceState) {}

    protected void initActionBar(ActionBar actionBar) {
        if (actionBar == null)
            return;
        if (hasBackButton()) {
            mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
            int layoutRes = getActionBarCustomView();
            View view = inflateView(layoutRes == 0 ? R.layout.actionbar_custom_backtitle
                    : layoutRes);
            View back = view.findViewById(R.id.btn_back);
            if (back == null) {
                throw new IllegalArgumentException(
                        "can not find R.id.btn_back in customView");
            }
            back.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    TDevice.hideSoftKeyboard(getCurrentFocus());
                    onBackPressed();
                }
            });
            mTvActionTitle = (TextView) view
                    .findViewById(R.id.tv_actionbar_title);
            if (mTvActionTitle == null) {
                throw new IllegalArgumentException(
                        "can not find R.id.tv_actionbar_title in customView");
            }
            int titleRes = getActionBarTitle();
            if (titleRes != 0) {
                mTvActionTitle.setText(titleRes);
            }
            LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT);
            actionBar.setCustomView(view, params);
            View spinner = actionBar.getCustomView().findViewById(R.id.spinner);
            if (haveSpinner()) {
                spinner.setVisibility(View.VISIBLE);
            } else {
                spinner.setVisibility(View.GONE);
            }
        } else {
            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE);
            actionBar.setDisplayUseLogoEnabled(false);
            int titleRes = getActionBarTitle();
            if (titleRes != 0) {
                actionBar.setTitle(titleRes);
            }
        }
    }

    protected Spinner getSpinner() {
        return (Spinner) mActionBar.getCustomView().findViewById(R.id.spinner);
    }

    public void setActionBarTitle(int resId) {
        if (resId != 0) {
            setActionBarTitle(getString(resId));
        }
    }

    public void setActionBarTitle(String title) {
        if (StringUtils.isEmpty(title)) {
            title = getString(R.string.app_name);
        }
        if (hasActionBar() && mActionBar != null) {
            if (mTvActionTitle != null) {
                mTvActionTitle.setText(title);
            }
            mActionBar.setTitle(title);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
            break;

        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    public void showToast(int msgResid, int icon, int gravity) {
        showToast(getString(msgResid), icon, gravity);
    }

    public void showToast(String message, int icon, int gravity) {
        CommonToast toast = new CommonToast(this);
        toast.setMessage(message);
        toast.setMessageIc(icon);
        toast.setLayoutGravity(gravity);
        toast.show();
    }

    @Override
    public WaitDialog showWaitDialog() {
        return showWaitDialog(R.string.loading);
    }

    @Override
    public WaitDialog showWaitDialog(int resid) {
        return showWaitDialog(getString(resid));
    }

    @Override
    public WaitDialog showWaitDialog(String message) {
        if (_isVisible) {
            if (_waitDialog == null) {
                _waitDialog = DialogHelper.getWaitDialog(this, message);
            }
            if (_waitDialog != null) {
                _waitDialog.setMessage(message);
                _waitDialog.show();
            }
            return _waitDialog;
        }
        return null;
    }

    @Override
    public void hideWaitDialog() {
        if (_isVisible && _waitDialog != null) {
            try {
                _waitDialog.dismiss();
                _waitDialog = null;
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {

        // setOverflowIconVisible(featureId, menu);
        return super.onMenuOpened(featureId, menu);
    }
}

 

 

 

 

 

 

 

BaseFragment.java

package net.oschina.app.base;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.interf.BaseFragmentInterface;
import net.oschina.app.ui.dialog.DialogControl;
import net.oschina.app.ui.dialog.WaitDialog;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * 碎片基类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年9月25日 上午11:18:46
 * 
 */
public class BaseFragment extends Fragment implements
        android.view.View.OnClickListener, BaseFragmentInterface {
    public static final int STATE_NONE = 0;
    public static final int STATE_REFRESH = 1;
    public static final int STATE_LOADMORE = 2;
    public static final int STATE_NOMORE = 3;
    public static final int STATE_PRESSNONE = 4;// 正在下拉但还没有到刷新的状态
    public static int mState = STATE_NONE;

    protected LayoutInflater mInflater;

    public AppContext getApplication() {
        return (AppContext) getActivity().getApplication();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        this.mInflater = inflater;
        View view = super.onCreateView(inflater, container, savedInstanceState);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    protected int getLayoutId() {
        return 0;
    }

    protected View inflateView(int resId) {
        return this.mInflater.inflate(resId, null);
    }

    public boolean onBackPressed() {
        return false;
    }

    protected void hideWaitDialog() {
        FragmentActivity activity = getActivity();
        if (activity instanceof DialogControl) {
            ((DialogControl) activity).hideWaitDialog();
        }
    }

    protected WaitDialog showWaitDialog() {
        return showWaitDialog(R.string.loading);
    }

    protected WaitDialog showWaitDialog(int resid) {
        FragmentActivity activity = getActivity();
        if (activity instanceof DialogControl) {
            return ((DialogControl) activity).showWaitDialog(resid);
        }
        return null;
    }

    protected WaitDialog showWaitDialog(String resid) {
        FragmentActivity activity = getActivity();
        if (activity instanceof DialogControl) {
            return ((DialogControl) activity).showWaitDialog(resid);
        }
        return null;
    }

    @Override
    public void initView(View view) {

    }

    @Override
    public void initData() {

    }

    @Override
    public void onClick(View v) {

    }
}

 

 

 

 

 

 

BaseDetailFragment.java

package net.oschina.app.base;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.bean.Comment;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.Entity;
import net.oschina.app.bean.Report;
import net.oschina.app.bean.Result;
import net.oschina.app.bean.ResultBean;
import net.oschina.app.cache.CacheManager;
import net.oschina.app.ui.DetailActivity;
import net.oschina.app.ui.ReportDialog;
import net.oschina.app.ui.ShareDialog;
import net.oschina.app.ui.ShareDialog.OnSharePlatformClick;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.util.HTMLUtil;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;

import org.apache.http.Header;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v7.internal.widget.ListPopupWindow;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.TextHttpResponseHandler;
import com.umeng.socialize.bean.SHARE_MEDIA;
import com.umeng.socialize.controller.UMServiceFactory;
import com.umeng.socialize.controller.UMSocialService;
import com.umeng.socialize.controller.listener.SocializeListeners.UMAuthListener;
import com.umeng.socialize.exception.SocializeException;
import com.umeng.socialize.media.UMImage;
import com.umeng.socialize.sso.SinaSsoHandler;
import com.umeng.socialize.sso.UMQQSsoHandler;
import com.umeng.socialize.utils.OauthHelper;
import com.umeng.socialize.weixin.controller.UMWXHandler;
import com.umeng.socialize.weixin.media.CircleShareContent;
import com.umeng.socialize.weixin.media.WeiXinShareContent;

public abstract class BaseDetailFragment extends BaseFragment implements
        OnItemClickListener {

    public static final String INTENT_ACTION_COMMENT_CHANGED = "INTENT_ACTION_COMMENT_CHAGED";

    final UMSocialService mController = UMServiceFactory
            .getUMSocialService("com.umeng.share");

    private ListPopupWindow mMenuWindow;
    private MenuAdapter mMenuAdapter;

    protected EmptyLayout mEmptyLayout;

    public int mCommentCount = 0;

    protected WebView mWebView;

    protected AsyncHttpResponseHandler mCommentHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                ResultBean rsb = XmlUtils.toBean(ResultBean.class,
                        new ByteArrayInputStream(arg2));
                Result res = rsb.getResult();
                if (res.OK()) {
                    hideWaitDialog();
                    AppContext.showToastShort(R.string.comment_publish_success);

                    commentPubSuccess(rsb.getComment());
                } else {
                    hideWaitDialog();
                    AppContext.showToastShort(res.getErrorMessage());
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
            ((DetailActivity) getActivity()).emojiFragment.clean();
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            hideWaitDialog();
            AppContext.showToastShort(R.string.comment_publish_faile);
        }

        @Override
        public void onFinish() {
            ((DetailActivity) getActivity()).emojiFragment.hideAllKeyBoard();
        };
    };

    protected void recycleWebView() {
        if (mWebView != null) {
            mWebView.setVisibility(View.GONE);
            mWebView.removeAllViews();
            mWebView.destroy();
            mWebView = null;
        }
    }

    protected void onCommentChanged(int opt, int id, int catalog,
            boolean isBlog, Comment comment) {}

    private AsyncTask<String, Void, Entity> mCacheTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMenuAdapter = new MenuAdapter();
        setHasOptionsMenu(true);

        mController.getConfig().closeToast();
    }

    protected boolean hasReportMenu() {
        return false;
    }

    @Override
    public void onDestroyView() {
        recycleWebView();
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        cancelReadCache();
        recycleWebView();
        super.onDestroy();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        requestData(false);
    }

    protected String getCacheKey() {
        return null;
    }

    protected Entity parseData(InputStream is) throws Exception {
        return null;
    }

    protected Entity readData(Serializable seri) {
        return null;
    }

    protected void sendRequestData() {}

    protected void requestData(boolean refresh) {
        String key = getCacheKey();
        if (TDevice.hasInternet()
                && (!CacheManager.isExistDataCache(getActivity(), key) || refresh)) {
            sendRequestData();
        } else {
            readCacheData(key);
        }
    }

    // 刷新数据
    protected void sendRefresh() {
        sendRequestData();
    }

    private void readCacheData(String cacheKey) {
        cancelReadCache();
        mCacheTask = new CacheTask(getActivity()).execute(cacheKey);
    }

    private void cancelReadCache() {
        if (mCacheTask != null) {
            mCacheTask.cancel(true);
            mCacheTask = null;
        }
    }

    private class CacheTask extends AsyncTask<String, Void, Entity> {
        private final WeakReference<Context> mContext;

        private CacheTask(Context context) {
            mContext = new WeakReference<Context>(context);
        }

        @Override
        protected Entity doInBackground(String... params) {
            if (mContext.get() != null) {
                Serializable seri = CacheManager.readObject(mContext.get(),
                        params[0]);
                if (seri == null) {
                    return null;
                } else {
                    return readData(seri);
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Entity entity) {
            super.onPostExecute(entity);
            if (entity != null) {
                executeOnLoadDataSuccess(entity);
            } else {
                executeOnLoadDataError(null);
            }
            executeOnLoadFinish();
        }
    }

    private class SaveCacheTask extends AsyncTask<Void, Void, Void> {
        private final WeakReference<Context> mContext;
        private final Serializable seri;
        private final String key;

        private SaveCacheTask(Context context, Serializable seri, String key) {
            mContext = new WeakReference<Context>(context);
            this.seri = seri;
            this.key = key;
        }

        @Override
        protected Void doInBackground(Void... params) {
            CacheManager.saveObject(mContext.get(), seri, key);
            return null;
        }
    }

    protected AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                Entity entity = parseData(new ByteArrayInputStream(arg2));
                if (entity != null) {
                    mEmptyLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
                    executeOnLoadDataSuccess(entity);
                    saveCache(entity);
                } else {
                    throw new RuntimeException("load detail error");
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            // executeOnLoadDataError(arg3.getMessage());
            readCacheData(getCacheKey());
        }
    };

    private boolean mIsFavorited;

    protected void saveCache(Entity entity) {
        new SaveCacheTask(getActivity(), entity, getCacheKey()).execute();
    }

    protected void executeOnLoadDataSuccess(Entity entity) {}

    protected void executeOnLoadDataError(String object) {
        mEmptyLayout.setErrorType(EmptyLayout.NETWORK_ERROR);
        mEmptyLayout.setOnLayoutClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mState = STATE_REFRESH;
                mEmptyLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
                requestData(true);
            }
        });
    }

    protected void executeOnLoadFinish() {}

    protected void onFavoriteChanged(boolean flag) {
        ((DetailActivity) getActivity()).toolFragment.setFavorite(flag);
    }

    protected int getFavoriteTargetId() {
        return -1;
    }

    protected int getFavoriteTargetType() {
        return -1;
    }

    protected String getShareUrl() {
        return "";
    }

    protected String getShareTitle() {
        return getString(R.string.share_title);
    }

    protected String getShareContent() {
        return "";
    }

    /***
     * 获取去除html标签的body
     * 
     * @param body
     * @return
     */
    protected String getFilterHtmlBody(String body) {
        if (body == null)
            return "";
        return HTMLUtil.delHTMLTag(body.trim());
    }

    protected UMImage getShareImg() {
        UMImage img = new UMImage(getActivity(), R.drawable.ic_share);
        return img;
    }

    protected void commentPubSuccess(Comment comment) {}

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        if (position == 0) {
            handleFavoriteOrNot();
            handleShare();
        } else if (position == 1) {
            onReportMenuClick();
        } else if (position == 2) {

        }
        if (mMenuWindow != null) {
            mMenuWindow.dismiss();
            mMenuWindow = null;
        }
    }

    private final AsyncHttpResponseHandler mReportHandler = new TextHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, String arg2) {
            if (TextUtils.isEmpty(arg2)) {
                AppContext.showToastShort(R.string.tip_report_success);
            } else {
                AppContext.showToastShort(new String(arg2));
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, String arg2,
                Throwable arg3) {
            AppContext.showToastShort(R.string.tip_report_faile);
        }

        @Override
        public void onFinish() {
            hideWaitDialog();
        }
    };

    public void onReportMenuClick() {
        if (getRepotrId() == 0) {
            AppContext.showToast("正在加载,请稍等...");
        }
        if (!AppContext.getInstance().isLogin()) {
            UIHelper.showLoginActivity(getActivity());
            return;
        }
        int reportId = getRepotrId();

        final ReportDialog dialog = new ReportDialog(getActivity(),
                getRepotrUrl(), reportId);
        dialog.setCancelable(true);
        dialog.setTitle(R.string.report);
        dialog.setCanceledOnTouchOutside(true);
        dialog.setNegativeButton(R.string.cancle, null);
        dialog.setPositiveButton(R.string.ok,
                new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface d, int which) {
                        Report report = null;
                        if ((report = dialog.getReport()) != null) {
                            showWaitDialog(R.string.progress_submit);
                            OSChinaApi.report(report, mReportHandler);
                        }
                        d.dismiss();
                    }
                });
        dialog.show();
    }

    protected String getRepotrUrl() {
        return "";
    }

    protected int getRepotrId() {
        return 0;
    }

    /**
     * 收藏
     */
    public void handleFavoriteOrNot() {
        if (!TDevice.hasInternet()) {
            AppContext.showToastShort(R.string.tip_no_internet);
            return;
        }
        if (!AppContext.getInstance().isLogin()) {
            UIHelper.showLoginActivity(getActivity());
            return;
        }
        if (getFavoriteTargetId() == -1 || getFavoriteTargetType() == -1) {
            return;
        }
        int uid = AppContext.getInstance().getLoginUid();
        if (mIsFavorited) {
            OSChinaApi.delFavorite(uid, getFavoriteTargetId(),
                    getFavoriteTargetType(), mDelFavoriteHandler);
        } else {
            OSChinaApi.addFavorite(uid, getFavoriteTargetId(),
                    getFavoriteTargetType(), mAddFavoriteHandler);
        }
    }

    /**
     * 分享
     */
    public void handleShare() {
        if (TextUtils.isEmpty(getShareContent())
                || TextUtils.isEmpty(getShareUrl())) {
            AppContext.showToast("内容加载失败...");
            return;
        }
        final ShareDialog dialog = new ShareDialog(getActivity());
        dialog.setCancelable(true);
        dialog.setCanceledOnTouchOutside(true);
        dialog.setTitle(R.string.share_to);
        dialog.setOnPlatformClickListener(new OnSharePlatformClick() {
            @Override
            public void onPlatformClick(int id) {
                switch (id) {
                case R.id.ly_share_weichat_circle:
                    shareToWeiChatCircle();
                    break;
                case R.id.ly_share_weichat:
                    shareToWeiChat();
                    break;
                case R.id.ly_share_sina_weibo:
                    shareToSinaWeibo();
                    break;
                case R.id.ly_share_qq:
                    shareToQQ(SHARE_MEDIA.QQ);
                    break;
                case R.id.ly_share_copy_link:
                    TDevice.copyTextToBoard(getShareUrl());
                    break;
                case R.id.ly_share_more_option:
                    TDevice.showSystemShareOption(getActivity(),
                            getShareTitle(), getShareUrl());
                    break;
                default:
                    break;
                }
                dialog.dismiss();
            }
        });
        dialog.show();
    }

    @SuppressWarnings("deprecation")
    private void shareToWeiChatCircle() {
        // 支持微信朋友圈
        UMWXHandler wxCircleHandler = new UMWXHandler(getActivity(),
                Constants.WEICHAT_APPID);
        wxCircleHandler.setToCircle(true);
        wxCircleHandler.addToSocialSDK();
        // 设置微信朋友圈分享内容
        CircleShareContent circleMedia = new CircleShareContent();
        circleMedia.setShareContent(getShareContent());
        // 设置朋友圈title
        circleMedia.setTitle(getShareTitle());
        circleMedia.setShareImage(getShareImg());
        circleMedia.setTargetUrl(getShareUrl());
        mController.setShareMedia(circleMedia);
        mController.postShare(getActivity(), SHARE_MEDIA.WEIXIN_CIRCLE, null);
    }

    @SuppressWarnings("deprecation")
    private void shareToWeiChat() {
        // 添加微信平台
        UMWXHandler wxHandler = new UMWXHandler(getActivity(),
                Constants.WEICHAT_APPID);
        wxHandler.addToSocialSDK();
        // 设置微信好友分享内容
        WeiXinShareContent weixinContent = new WeiXinShareContent();
        // 设置分享文字
        weixinContent.setShareContent(getShareContent());
        // 设置title
        weixinContent.setTitle(getShareTitle());
        // 设置分享内容跳转URL
        weixinContent.setTargetUrl(getShareUrl());
        // 设置分享图片
        weixinContent.setShareImage(getShareImg());
        mController.setShareMedia(weixinContent);
        mController.postShare(getActivity(), SHARE_MEDIA.WEIXIN, null);
    }

    private void shareToSinaWeibo() {
        // 设置新浪微博SSO handler
        mController.getConfig().setSsoHandler(new SinaSsoHandler());
        if (OauthHelper.isAuthenticated(getActivity(), SHARE_MEDIA.SINA)) {
            shareContent(SHARE_MEDIA.SINA);
        } else {
            mController.doOauthVerify(getActivity(), SHARE_MEDIA.SINA,
                    new UMAuthListener() {

                        @Override
                        public void onStart(SHARE_MEDIA arg0) {}

                        @Override
                        public void onError(SocializeException arg0,
                                SHARE_MEDIA arg1) {}

                        @Override
                        public void onComplete(Bundle arg0, SHARE_MEDIA arg1) {
                            shareContent(SHARE_MEDIA.SINA);
                        }

                        @Override
                        public void onCancel(SHARE_MEDIA arg0) {}
                    });
        }
    }

    private void shareContent(SHARE_MEDIA media) {
        mController.setShareContent(getShareContent() + getShareUrl());
        mController.directShare(getActivity(), media, null);
    }

    protected void shareToQQ(SHARE_MEDIA media) {
        UMQQSsoHandler qqSsoHandler = new UMQQSsoHandler(getActivity(),
                Constants.QQ_APPID, Constants.QQ_APPKEY);
        qqSsoHandler.setTargetUrl(getShareUrl());
        qqSsoHandler.setTitle(getShareTitle());
        qqSsoHandler.addToSocialSDK();
        mController.setShareContent(getShareContent());
        mController.setShareImage(getShareImg());
        mController.postShare(getActivity(), media, null);
    }

    protected void notifyFavorite(boolean favorite) {
        mIsFavorited = favorite;
        FragmentActivity aty = getActivity();
        if (aty != null) {
            aty.supportInvalidateOptionsMenu();
        }
        if (mMenuAdapter != null) {
            mMenuAdapter.setFavorite(favorite);
        }
        onFavoriteChanged(favorite);
    }

    public boolean isFavorited() {
        return mIsFavorited;
    }

    @SuppressLint("ViewHolder")
    private static class MenuAdapter extends BaseAdapter {

        public void setFavorite(boolean favorite) {
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @SuppressLint("InflateParams")
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.list_cell_popup_menu, null);
            TextView name = (TextView) convertView.findViewById(R.id.tv_name);

            int iconResId = 0;
            // if (position == 0) {
            // name.setText(isFavorite ? R.string.detail_menu_unfavorite
            // : R.string.detail_menu_favorite);
            // iconResId = isFavorite ?
            // R.drawable.actionbar_menu_icn_unfavoirite
            // : R.drawable.actionbar_menu_icn_favoirite;
            // } else
            if (position == 0) {
                name.setText(parent.getResources().getString(
                        R.string.detail_menu_for_share));
                iconResId = R.drawable.abc_ic_menu_moreoverflow_normal_holo_dark;
            } else if (position == 1) {
                name.setText(parent.getResources().getString(
                        R.string.detail_menu_for_report));
                iconResId = R.drawable.abc_ic_menu_moreoverflow_normal_holo_dark;
            }
            Drawable drawable = AppContext.resources().getDrawable(iconResId);
            drawable.setBounds(0, 0, drawable.getMinimumWidth(),
                    drawable.getMinimumHeight());
            name.setCompoundDrawables(drawable, null, null, null);
            return convertView;
        }
    }

    private final AsyncHttpResponseHandler mAddFavoriteHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                Result res = XmlUtils.toBean(ResultBean.class,
                        new ByteArrayInputStream(arg2)).getResult();
                if (res.OK()) {
                    AppContext.showToastShort(R.string.add_favorite_success);
                    mMenuAdapter.setFavorite(true);
                    mMenuAdapter.notifyDataSetChanged();
                    mIsFavorited = true;
                    getActivity().supportInvalidateOptionsMenu();
                    onFavoriteChanged(true);
                    ImageView view = (ImageView) getActivity().findViewById(
                            R.id.action_favor);
                    view.setImageResource(R.drawable.ic_action_favor_on_normal);
                } else {
                    AppContext.showToastShort(res.getErrorMessage());
                }

            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            AppContext.showToastShort(R.string.add_favorite_faile);
        }
    };

    private final AsyncHttpResponseHandler mDelFavoriteHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                Result res = XmlUtils.toBean(ResultBean.class,
                        new ByteArrayInputStream(arg2)).getResult();
                if (res.OK()) {
                    AppContext.showToastShort(R.string.del_favorite_success);
                    mMenuAdapter.setFavorite(false);
                    mMenuAdapter.notifyDataSetChanged();
                    mIsFavorited = false;
                    getActivity().supportInvalidateOptionsMenu();
                    onFavoriteChanged(false);
                    ImageView view = (ImageView) getActivity().findViewById(
                            R.id.action_favor);
                    view.setImageResource(R.drawable.ic_action_favor);
                } else {
                    AppContext.showToastShort(res.getErrorMessage());
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            AppContext.showToastShort(R.string.del_favorite_faile);
        }
    };

    public abstract int getCommentCount();

    @Override
    public void onClick(View v) {}

    @Override
    public void initView(View view) {}

    public void onclickWriteComment() {}

    @Override
    public void initData() {}
}

 

 

 

 

 

 

BaseListFragment.java

package net.oschina.app.base;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.bean.Entity;
import net.oschina.app.bean.ListEntity;
import net.oschina.app.bean.Result;
import net.oschina.app.bean.ResultBean;
import net.oschina.app.cache.CacheManager;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.XmlUtils;

import org.apache.http.Header;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

import com.loopj.android.http.AsyncHttpResponseHandler;

@SuppressLint("NewApi")
public abstract class BaseListFragment<T extends Entity> extends BaseFragment
        implements SwipeRefreshLayout.OnRefreshListener, OnItemClickListener,
        OnScrollListener {

    public static final String BUNDLE_KEY_CATALOG = "BUNDLE_KEY_CATALOG";

    @InjectView(R.id.swiperefreshlayout)
    protected SwipeRefreshLayout mSwipeRefreshLayout;

    @InjectView(R.id.listview)
    protected ListView mListView;

    protected ListBaseAdapter<T> mAdapter;

    @InjectView(R.id.error_layout)
    protected EmptyLayout mErrorLayout;

    protected int mStoreEmptyState = -1;

    protected int mCurrentPage = 0;

    protected int mCatalog = 1;
    // 错误信息
    protected Result mResult;

    private AsyncTask<String, Void, ListEntity<T>> mCacheTask;
    private ParserTask mParserTask;

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_pull_refresh_listview;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(getLayoutId(), container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ButterKnife.inject(this, view);
        initView(view);
    }

    @Override
    public void onCreate(android.os.Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
            mCatalog = args.getInt(BUNDLE_KEY_CATALOG, 0);
        }
    }

    @Override
    public void initView(View view) {
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeResources(
                R.color.swiperefresh_color1, R.color.swiperefresh_color2,
                R.color.swiperefresh_color3, R.color.swiperefresh_color4);

        mErrorLayout.setOnLayoutClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                mCurrentPage = 0;
                mState = STATE_REFRESH;
                mErrorLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
                requestData(true);
            }
        });

        mListView.setOnItemClickListener(this);
        mListView.setOnScrollListener(this);

        if (mAdapter != null) {
            mListView.setAdapter(mAdapter);
            mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
        } else {
            mAdapter = getListAdapter();
            mListView.setAdapter(mAdapter);

            if (requestDataIfViewCreated()) {
                mErrorLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
                mState = STATE_NONE;
                requestData(false);
            } else {
                mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
            }

        }
        if (mStoreEmptyState != -1) {
            mErrorLayout.setErrorType(mStoreEmptyState);
        }
    }

    @Override
    public void onDestroyView() {
        mStoreEmptyState = mErrorLayout.getErrorState();
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        cancelReadCacheTask();
        cancelParserTask();
        super.onDestroy();
    }

    protected abstract ListBaseAdapter<T> getListAdapter();

    // 下拉刷新数据
    @Override
    public void onRefresh() {
        if (mState == STATE_REFRESH) {
            return;
        }
        // 设置顶部正在刷新
        mListView.setSelection(0);
        setSwipeRefreshLoadingState();
        mCurrentPage = 0;
        mState = STATE_REFRESH;
        requestData(true);
    }

    protected boolean requestDataIfViewCreated() {
        return true;
    }

    protected String getCacheKeyPrefix() {
        return null;
    }

    protected ListEntity<T> parseList(InputStream is) throws Exception {
        return null;
    }

    protected ListEntity<T> readList(Serializable seri) {
        return null;
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {}

    private String getCacheKey() {
        return new StringBuilder(getCacheKeyPrefix()).append("_")
                .append(mCurrentPage).toString();
    }

    // 是否需要自动刷新
    protected boolean needAutoRefresh() {
        return true;
    }

    /***
     * 获取列表数据
     * 
     * 
     * @author 火蚁 2015-2-9 下午3:16:12
     * 
     * @return void
     * @param refresh
     */
    protected void requestData(boolean refresh) {
        String key = getCacheKey();
        if (isReadCacheData(refresh)) {
            readCacheData(key);
        } else {
            // 取新的数据
            sendRequestData();
        }
    }

    /***
     * 判断是否需要读取缓存的数据
     * 
     * @author 火蚁 2015-2-10 下午2:41:02
     * 
     * @return boolean
     * @param refresh
     * @return
     */
    protected boolean isReadCacheData(boolean refresh) {
        String key = getCacheKey();
        if (!TDevice.hasInternet()) {
            return true;
        }
        // 第一页若不是主动刷新,缓存存在,优先取缓存的
        if (CacheManager.isExistDataCache(getActivity(), key) && !refresh
                && mCurrentPage == 0) {
            return true;
        }
        // 其他页数的,缓存存在以及还没有失效,优先取缓存的
        if (CacheManager.isExistDataCache(getActivity(), key)
                && !CacheManager.isCacheDataFailure(getActivity(), key)
                && mCurrentPage != 0) {
            return true;
        }

        return false;
    }

    // 是否到时间去刷新数据了
    private boolean onTimeRefresh() {
        String lastRefreshTime = AppContext.getLastRefreshTime(getCacheKey());
        String currTime = StringUtils.getCurTimeStr();
        long diff = StringUtils.calDateDifferent(lastRefreshTime, currTime);
        return needAutoRefresh() && diff > getAutoRefreshTime();
    }

    /***
     * 自动刷新的时间
     * 
     * 默认:自动刷新的时间为半天时间
     * 
     * @author 火蚁 2015-2-9 下午5:55:11
     * 
     * @return long
     * @return
     */
    protected long getAutoRefreshTime() {
        return 12 * 60 * 60;
    }

    @Override
    public void onResume() {
        super.onResume();
        if (onTimeRefresh()) {
            onRefresh();
        }
    }

    protected void sendRequestData() {}

    private void readCacheData(String cacheKey) {
        cancelReadCacheTask();
        mCacheTask = new CacheTask(getActivity()).execute(cacheKey);
    }

    private void cancelReadCacheTask() {
        if (mCacheTask != null) {
            mCacheTask.cancel(true);
            mCacheTask = null;
        }
    }

    private class CacheTask extends AsyncTask<String, Void, ListEntity<T>> {
        private final WeakReference<Context> mContext;

        private CacheTask(Context context) {
            mContext = new WeakReference<Context>(context);
        }

        @Override
        protected ListEntity<T> doInBackground(String... params) {
            Serializable seri = CacheManager.readObject(mContext.get(),
                    params[0]);
            if (seri == null) {
                return null;
            } else {
                return readList(seri);
            }
        }

        @Override
        protected void onPostExecute(ListEntity<T> list) {
            super.onPostExecute(list);
            if (list != null) {
                executeOnLoadDataSuccess(list.getList());
            } else {
                executeOnLoadDataError(null);
            }
            executeOnLoadFinish();
        }
    }

    private class SaveCacheTask extends AsyncTask<Void, Void, Void> {
        private final WeakReference<Context> mContext;
        private final Serializable seri;
        private final String key;

        private SaveCacheTask(Context context, Serializable seri, String key) {
            mContext = new WeakReference<Context>(context);
            this.seri = seri;
            this.key = key;
        }

        @Override
        protected Void doInBackground(Void... params) {
            CacheManager.saveObject(mContext.get(), seri, key);
            return null;
        }
    }

    protected AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBytes) {
            if (mCurrentPage == 0 && needAutoRefresh()) {
                AppContext.putToLastRefreshTime(getCacheKey(),
                        StringUtils.getCurTimeStr());
            }
            if (isAdded()) {
                if (mState == STATE_REFRESH) {
                    onRefreshNetworkSuccess();
                }
                executeParserTask(responseBytes);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            if (isAdded()) {
                readCacheData(getCacheKey());
            }
        }
    };

    protected void executeOnLoadDataSuccess(List<T> data) {
        if (data == null) {
            data = new ArrayList<T>();
        }

        if (mResult != null && !mResult.OK()) {
            AppContext.showToast(mResult.getErrorMessage());
            // 注销登陆,密码已经修改,cookie,失效了
            AppContext.getInstance().Logout();
        }

        mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
        if (mCurrentPage == 0) {
            mAdapter.clear();
        }

        for (int i = 0; i < data.size(); i++) {
            if (compareTo(mAdapter.getData(), data.get(i))) {
                data.remove(i);
                i--;
            }
        }
        int adapterState = ListBaseAdapter.STATE_EMPTY_ITEM;
        if ((mAdapter.getCount() + data.size()) == 0) {
            adapterState = ListBaseAdapter.STATE_EMPTY_ITEM;
        } else if (data.size() == 0
                || (data.size() < getPageSize() && mCurrentPage == 0)) {
            adapterState = ListBaseAdapter.STATE_NO_MORE;
            mAdapter.notifyDataSetChanged();
        } else {
            adapterState = ListBaseAdapter.STATE_LOAD_MORE;
        }
        mAdapter.setState(adapterState);
        mAdapter.addData(data);
        // 判断等于是因为最后有一项是listview的状态
        if (mAdapter.getCount() == 1) {

            if (needShowEmptyNoData()) {
                mErrorLayout.setErrorType(EmptyLayout.NODATA);
            } else {
                mAdapter.setState(ListBaseAdapter.STATE_EMPTY_ITEM);
                mAdapter.notifyDataSetChanged();
            }
        }
    }

    /**
     * 是否需要隐藏listview,显示无数据状态
     * 
     * @author 火蚁 2015-1-27 下午6:18:59
     * 
     */
    protected boolean needShowEmptyNoData() {
        return true;
    }

    protected boolean compareTo(List<? extends Entity> data, Entity enity) {
        int s = data.size();
        if (enity != null) {
            for (int i = 0; i < s; i++) {
                if (enity.getId() == data.get(i).getId()) {
                    return true;
                }
            }
        }
        return false;
    }

    protected int getPageSize() {
        return AppContext.PAGE_SIZE;
    }

    protected void onRefreshNetworkSuccess() {}

    protected void executeOnLoadDataError(String error) {
        if (mCurrentPage == 0
                && !CacheManager.isExistDataCache(getActivity(), getCacheKey())) {
            mErrorLayout.setErrorType(EmptyLayout.NETWORK_ERROR);
        } else {
            mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
            mAdapter.setState(ListBaseAdapter.STATE_NETWORK_ERROR);
            mAdapter.notifyDataSetChanged();
        }
    }

    // 完成刷新
    protected void executeOnLoadFinish() {
        setSwipeRefreshLoadedState();
        mState = STATE_NONE;
    }

    /** 设置顶部正在加载的状态 */
    private void setSwipeRefreshLoadingState() {
        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.setRefreshing(true);
            // 防止多次重复刷新
            mSwipeRefreshLayout.setEnabled(false);
        }
    }

    /** 设置顶部加载完毕的状态 */
    private void setSwipeRefreshLoadedState() {
        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.setRefreshing(false);
            mSwipeRefreshLayout.setEnabled(true);
        }
    }

    private void executeParserTask(byte[] data) {
        cancelParserTask();
        mParserTask = new ParserTask(data);
        mParserTask.execute();
    }

    private void cancelParserTask() {
        if (mParserTask != null) {
            mParserTask.cancel(true);
            mParserTask = null;
        }
    }

    class ParserTask extends AsyncTask<Void, Void, String> {

        private final byte[] reponseData;
        private boolean parserError;
        private List<T> list;

        public ParserTask(byte[] data) {
            this.reponseData = data;
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                ListEntity<T> data = parseList(new ByteArrayInputStream(
                        reponseData));
                new SaveCacheTask(getActivity(), data, getCacheKey()).execute();
                list = data.getList();
                if (list == null) {
                    ResultBean resultBean = XmlUtils.toBean(ResultBean.class,
                            reponseData);
                    if (resultBean != null) {
                        mResult = resultBean.getResult();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();

                parserError = true;
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if (parserError) {
                readCacheData(getCacheKey());
            } else {
                executeOnLoadDataSuccess(list);
                executeOnLoadFinish();
            }
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (mAdapter == null || mAdapter.getCount() == 0) {
            return;
        }
        // 数据已经全部加载,或数据为空时,或正在加载,不处理滚动事件
        if (mState == STATE_LOADMORE || mState == STATE_REFRESH) {
            return;
        }
        // 判断是否滚动到底部
        boolean scrollEnd = false;
        try {
            if (view.getPositionForView(mAdapter.getFooterView()) == view
                    .getLastVisiblePosition())
                scrollEnd = true;
        } catch (Exception e) {
            scrollEnd = false;
        }

        if (mState == STATE_NONE && scrollEnd) {
            if (mAdapter.getState() == ListBaseAdapter.STATE_LOAD_MORE
                    || mAdapter.getState() == ListBaseAdapter.STATE_NETWORK_ERROR) {
                mCurrentPage++;
                mState = STATE_LOADMORE;
                requestData(false);
                mAdapter.setFooterViewLoading();
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        // 数据已经全部加载,或数据为空时,或正在加载,不处理滚动事件
        // if (mState == STATE_NOMORE || mState == STATE_LOADMORE
        // || mState == STATE_REFRESH) {
        // return;
        // }
        // if (mAdapter != null
        // && mAdapter.getDataSize() > 0
        // && mListView.getLastVisiblePosition() == (mListView.getCount() - 1))
        // {
        // if (mState == STATE_NONE
        // && mAdapter.getState() == ListBaseAdapter.STATE_LOAD_MORE) {
        // mState = STATE_LOADMORE;
        // mCurrentPage++;
        // requestData(true);
        // }
        // }
    }

    /**
     * 保存已读的文章列表
     * 
     * @param view
     * @param prefFileName
     * @param key
     */
    protected void saveToReadedList(final View view, final String prefFileName,
            final String key) {
        // 放入已读列表
        AppContext.putReadedPostList(prefFileName, key, "true");
        TextView tvTitle = (TextView) view.findViewById(R.id.tv_title);
        if (tvTitle != null) {
            tvTitle.setTextColor(0xff9a9a9a);
        }
    }
}

 

 

 

 

 

 

BaseViewPagerFragment.java

package net.oschina.app.base;

import net.oschina.app.R;
import net.oschina.app.adapter.ViewPageFragmentAdapter;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.widget.PagerSlidingTabStrip;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * 带有导航条的基类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年11月6日 下午4:59:50
 * 
 */
public abstract class BaseViewPagerFragment extends BaseFragment {

    protected PagerSlidingTabStrip mTabStrip;
    protected ViewPager mViewPager;
    protected ViewPageFragmentAdapter mTabsAdapter;
    protected EmptyLayout mErrorLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.base_viewpage_fragment, null);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        mTabStrip = (PagerSlidingTabStrip) view
                .findViewById(R.id.pager_tabstrip);

        mViewPager = (ViewPager) view.findViewById(R.id.pager);

        mErrorLayout = (EmptyLayout) view.findViewById(R.id.error_layout);

        mTabsAdapter = new ViewPageFragmentAdapter(getChildFragmentManager(),
                mTabStrip, mViewPager);
        setScreenPageLimit();
        onSetupTabAdapter(mTabsAdapter);
        // if (savedInstanceState != null) {
        // int pos = savedInstanceState.getInt("position");
        // mViewPager.setCurrentItem(pos, true);
        // }
    }
    
    protected void setScreenPageLimit() {
    }

    // @Override
    // public void onSaveInstanceState(Bundle outState) {
    // //No call for super(). Bug on API Level > 11.
    // if (outState != null && mViewPager != null) {
    // outState.putInt("position", mViewPager.getCurrentItem());
    // }
    // //super.onSaveInstanceState(outState);
    // }

    protected abstract void onSetupTabAdapter(ViewPageFragmentAdapter adapter);
}

 

 

 

 

 

 

 

BeseHaveHeaderListFragment.java

package net.oschina.app.base;

import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;

import net.oschina.app.bean.Entity;
import net.oschina.app.cache.CacheManager;
import net.oschina.app.ui.empty.EmptyLayout;

import org.apache.http.Header;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import butterknife.ButterKnife;

import com.loopj.android.http.AsyncHttpResponseHandler;

/**
 * 需要加入header的BaseListFragment
 * 
 * @desc 应用场景:如动弹详情、团队任务详情这些, 即是头部显示详情,然后下面显示评论列表的
 * 
 *       BeseHaveHeaderListFragment.java
 * 
 * @author 火蚁(http://my.oschina.net/u/253900)
 * 
 * @data 2015-1-27 下午3:02:42
 */
public abstract class BeseHaveHeaderListFragment<T1 extends Entity, T2 extends Serializable>
        extends BaseListFragment<T1> {

    protected T2 detailBean;// list 头部的详情实体类

    protected Activity aty;

    protected final AsyncHttpResponseHandler mDetailHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                if (arg2 != null) {
                    T2 detail = getDetailBean(new ByteArrayInputStream(arg2));
                    if (detail != null) {
                        requstListData();
                        executeOnLoadDetailSuccess(detail);
                        new SaveCacheTask(getActivity(), detail,
                                getDetailCacheKey()).execute();
                    } else {
                        onFailure(arg0, arg1, arg2, null);
                    }
                } else {
                    throw new RuntimeException("load detail error");
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            readDetailCacheData(getDetailCacheKey());
        }
    };

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // 通过注解绑定控件
        ButterKnife.inject(this, view);
        mListView.addHeaderView(initHeaderView());
        aty = getActivity();
        super.initView(view);
        requestDetailData(isRefresh());
    }

    protected boolean isRefresh() {
        return false;
    }

    protected abstract void requestDetailData(boolean isRefresh);

    protected abstract View initHeaderView();

    protected abstract String getDetailCacheKey();

    protected abstract void executeOnLoadDetailSuccess(T2 detailBean);

    protected abstract T2 getDetailBean(ByteArrayInputStream is);

    @Override
    protected boolean requestDataIfViewCreated() {
        return false;
    }

    private void requstListData() {
        mState = STATE_REFRESH;
        mAdapter.setState(ListBaseAdapter.STATE_LOAD_MORE);
        sendRequestData();
    }

    /***
     * 带有header view的listfragment不需要显示是否数据为空
     */
    @Override
    protected boolean needShowEmptyNoData() {
        return false;
    }

    protected void readDetailCacheData(String cacheKey) {
        new ReadCacheTask(getActivity()).execute(cacheKey);
    }

    private class SaveCacheTask extends AsyncTask<Void, Void, Void> {
        private final WeakReference<Context> mContext;
        private final Serializable seri;
        private final String key;

        private SaveCacheTask(Context context, Serializable seri, String key) {
            mContext = new WeakReference<Context>(context);
            this.seri = seri;
            this.key = key;
        }

        @Override
        protected Void doInBackground(Void... params) {
            CacheManager.saveObject(mContext.get(), seri, key);
            return null;
        }
    }

    private class ReadCacheTask extends AsyncTask<String, Void, T2> {
        private final WeakReference<Context> mContext;

        private ReadCacheTask(Context context) {
            mContext = new WeakReference<Context>(context);
        }

        @Override
        protected T2 doInBackground(String... params) {
            if (mContext.get() != null) {
                Serializable seri = CacheManager.readObject(mContext.get(),
                        params[0]);
                if (seri == null) {
                    return null;
                } else {
                    return (T2) seri;
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(T2 t) {
            super.onPostExecute(t);
            if (t != null) {
                requstListData();
                executeOnLoadDetailSuccess(t);
            }
        }
    }

    @Override
    protected void executeOnLoadDataError(String error) {
        mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
        mAdapter.setState(ListBaseAdapter.STATE_NETWORK_ERROR);
        mAdapter.notifyDataSetChanged();
    }

    @SuppressWarnings("unchecked")
    protected <T extends View> T findHeaderView(View headerView, int viewId) {
        return (T) headerView.findViewById(viewId);
    }
}

 

 

 

 

 

 

 

ListBaseAdapter.java

package net.oschina.app.base;

import java.util.ArrayList;
import java.util.List;

import net.oschina.app.R;
import net.oschina.app.bean.Entity;
import net.oschina.app.emoji.InputHelper;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TDevice;
import net.oschina.app.widget.MyLinkMovementMethod;
import net.oschina.app.widget.MyURLSpan;
import net.oschina.app.widget.TweetTextView;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

public class ListBaseAdapter<T extends Entity> extends BaseAdapter {
    public static final int STATE_EMPTY_ITEM = 0;
    public static final int STATE_LOAD_MORE = 1;
    public static final int STATE_NO_MORE = 2;
    public static final int STATE_NO_DATA = 3;
    public static final int STATE_LESS_ONE_PAGE = 4;
    public static final int STATE_NETWORK_ERROR = 5;
    public static final int STATE_OTHER = 6;

    protected int state = STATE_LESS_ONE_PAGE;

    protected int _loadmoreText;
    protected int _loadFinishText;
    protected int _noDateText;
    protected int mScreenWidth;

    private LayoutInflater mInflater;

    protected LayoutInflater getLayoutInflater(Context context) {
        if (mInflater == null) {
            mInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
        return mInflater;
    }

    public void setScreenWidth(int width) {
        mScreenWidth = width;
    }

    public void setState(int state) {
        this.state = state;
    }

    public int getState() {
        return this.state;
    }

    protected ArrayList<T> mDatas = new ArrayList<T>();

    public ListBaseAdapter() {
        _loadmoreText = R.string.loading;
        _loadFinishText = R.string.loading_no_more;
        _noDateText = R.string.error_view_no_data;
    }

    @Override
    public int getCount() {
        switch (getState()) {
        case STATE_EMPTY_ITEM:
            return getDataSize() + 1;
        case STATE_NETWORK_ERROR:
        case STATE_LOAD_MORE:
            return getDataSize() + 1;
        case STATE_NO_DATA:
            return 1;
        case STATE_NO_MORE:
            return getDataSize() + 1;
        case STATE_LESS_ONE_PAGE:
            return getDataSize();
        default:
            break;
        }
        return getDataSize();
    }

    public int getDataSize() {
        return mDatas.size();
    }

    @Override
    public T getItem(int arg0) {
        if (mDatas.size() > arg0) {
            return mDatas.get(arg0);
        }
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        return arg0;
    }

    public void setData(ArrayList<T> data) {
        mDatas = data;
        notifyDataSetChanged();
    }

    public ArrayList<T> getData() {
        return mDatas == null ? (mDatas = new ArrayList<T>()) : mDatas;
    }

    public void addData(List<T> data) {
        if (mDatas != null && data != null && !data.isEmpty()) {
            mDatas.addAll(data);
        }
        notifyDataSetChanged();
    }

    public void addItem(T obj) {
        if (mDatas != null) {
            mDatas.add(obj);
        }
        notifyDataSetChanged();
    }

    public void addItem(int pos, T obj) {
        if (mDatas != null) {
            mDatas.add(pos, obj);
        }
        notifyDataSetChanged();
    }

    public void removeItem(Object obj) {
        mDatas.remove(obj);
        notifyDataSetChanged();
    }

    public void clear() {
        mDatas.clear();
        notifyDataSetChanged();
    }

    public void setLoadmoreText(int loadmoreText) {
        _loadmoreText = loadmoreText;
    }

    public void setLoadFinishText(int loadFinishText) {
        _loadFinishText = loadFinishText;
    }

    public void setNoDataText(int noDataText) {
        _noDateText = noDataText;
    }

    protected boolean loadMoreHasBg() {
        return true;
    }

    @SuppressWarnings("deprecation")
    @SuppressLint("InflateParams")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (position == getCount() - 1) {// 最后一条
            // if (position < _data.size()) {
            // position = getCount() - 2; // footview
            // }
            if (getState() == STATE_LOAD_MORE || getState() == STATE_NO_MORE
                    || state == STATE_EMPTY_ITEM
                    || getState() == STATE_NETWORK_ERROR) {
                this.mFooterView = (LinearLayout) LayoutInflater.from(
                        parent.getContext()).inflate(R.layout.list_cell_footer,
                        null);
                if (!loadMoreHasBg()) {
                    mFooterView.setBackgroundDrawable(null);
                }
                ProgressBar progress = (ProgressBar) mFooterView
                        .findViewById(R.id.progressbar);
                TextView text = (TextView) mFooterView.findViewById(R.id.text);
                switch (getState()) {
                case STATE_LOAD_MORE:
                    setFooterViewLoading();
                    break;
                case STATE_NO_MORE:
                    mFooterView.setVisibility(View.VISIBLE);
                    progress.setVisibility(View.GONE);
                    text.setVisibility(View.VISIBLE);
                    text.setText(_loadFinishText);
                    break;
                case STATE_EMPTY_ITEM:
                    progress.setVisibility(View.GONE);
                    mFooterView.setVisibility(View.VISIBLE);
                    text.setText(_noDateText);
                    break;
                case STATE_NETWORK_ERROR:
                    mFooterView.setVisibility(View.VISIBLE);
                    progress.setVisibility(View.GONE);
                    text.setVisibility(View.VISIBLE);
                    if (TDevice.hasInternet()) {
                        text.setText("加载出错了");
                    } else {
                        text.setText("没有可用的网络");
                    }
                    break;
                default:
                    progress.setVisibility(View.GONE);
                    mFooterView.setVisibility(View.GONE);
                    text.setVisibility(View.GONE);
                    break;
                }
                return mFooterView;
            }
        }
        if (position < 0) {
            position = 0; // 若列表没有数据,是没有footview/headview的
        }
        return getRealView(position, convertView, parent);
    }

    protected View getRealView(int position, View convertView, ViewGroup parent) {
        return null;
    }

    private LinearLayout mFooterView;

    public View getFooterView() {
        return this.mFooterView;
    }

    public void setFooterViewLoading(String loadMsg) {
        ProgressBar progress = (ProgressBar) mFooterView
                .findViewById(R.id.progressbar);
        TextView text = (TextView) mFooterView.findViewById(R.id.text);
        mFooterView.setVisibility(View.VISIBLE);
        progress.setVisibility(View.VISIBLE);
        text.setVisibility(View.VISIBLE);
        if (StringUtils.isEmpty(loadMsg)) {
            text.setText(_loadmoreText);
        } else {
            text.setText(loadMsg);
        }
    }

    public void setFooterViewLoading() {
        setFooterViewLoading("");
    }

    public void setFooterViewText(String msg) {
        ProgressBar progress = (ProgressBar) mFooterView
                .findViewById(R.id.progressbar);
        TextView text = (TextView) mFooterView.findViewById(R.id.text);
        mFooterView.setVisibility(View.VISIBLE);
        progress.setVisibility(View.GONE);
        text.setVisibility(View.VISIBLE);
        text.setText(msg);
    }

    protected void setContent(TweetTextView contentView, String content) {
        contentView.setMovementMethod(MyLinkMovementMethod.a());
        contentView.setFocusable(false);
        contentView.setDispatchToParent(true);
        contentView.setLongClickable(false);
        Spanned span = Html.fromHtml(TweetTextView.modifyPath(content));
        span = InputHelper.displayEmoji(contentView.getResources(),
                span.toString());
        contentView.setText(span);
        MyURLSpan.parseLinkText(contentView, span);
    }

    protected void setText(TextView textView, String text, boolean needGone) {
        if (text == null || TextUtils.isEmpty(text)) {
            if (needGone) {
                textView.setVisibility(View.GONE);
            }
        } else {
            textView.setText(text);
        }
    }

    protected void setText(TextView textView, String text) {
        setText(textView, text, false);
    }
}

 

 

 

 

 

 

AppConfig.java

package net.oschina.app;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.preference.PreferenceManager;

/**
 * 应用程序配置类:用于保存用户相关信息及设置
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年9月25日 下午5:29:00
 * 
 */
public class AppConfig {

    private final static String APP_CONFIG = "config";

    public final static String CONF_COOKIE = "cookie";

    public final static String CONF_APP_UNIQUEID = "APP_UNIQUEID";

    public static final String KEY_LOAD_IMAGE = "KEY_LOAD_IMAGE";
    public static final String KEY_NOTIFICATION_ACCEPT = "KEY_NOTIFICATION_ACCEPT";
    public static final String KEY_NOTIFICATION_SOUND = "KEY_NOTIFICATION_SOUND";
    public static final String KEY_NOTIFICATION_VIBRATION = "KEY_NOTIFICATION_VIBRATION";
    public static final String KEY_NOTIFICATION_DISABLE_WHEN_EXIT = "KEY_NOTIFICATION_DISABLE_WHEN_EXIT";
    public static final String KEY_CHECK_UPDATE = "KEY_CHECK_UPDATE";
    public static final String KEY_DOUBLE_CLICK_EXIT = "KEY_DOUBLE_CLICK_EXIT";

    public static final String LAST_QUESTION_CATEGORY_IDX = "LAST_QUESTION_CATEGORY_IDX";
    public static final String KEY_DAILY_ENGLISH = "KEY_DAILY_ENGLISH";
    public static final String KEY_GET_LAST_DAILY_ENG = "KEY_GET_LAST_DAILY_ENG";
    public static final String KEY_TWEET_DRAFT = "KEY_TWEET_DRAFT";
    public static final String KEY_NOTE_DRAFT = "KEY_NOTE_DRAFT";
    public static final String KEY_QUESTION_TITLE_DRAFT = "KEY_QUESTION_TITLE_DRAFT";
    public static final String KEY_QUESTION_CONTENT_DRAFT = "KEY_QUESTION_CONTENT_DRAFT";
    public static final String KEY_QUESTION_TYPE_DRAFT = "KEY_QUESTION_TYPE_DRAFT";
    public static final String KEY_QUESTION_LMK_DRAFT = "KEY_QUESTION_LMK_DRAFT";

    public static final String KEY_FRITST_START = "KEY_FRIST_START";

    public static final String APP_QQ_KEY = "100942993";

    // 默认存放图片的路径
    public final static String DEFAULT_SAVE_IMAGE_PATH = Environment
            .getExternalStorageDirectory()
            + File.separator
            + "OSChina"
            + File.separator + "osc_img" + File.separator;

    // 默认存放文件下载的路径
    public final static String DEFAULT_SAVE_FILE_PATH = Environment
            .getExternalStorageDirectory()
            + File.separator
            + "OSChina"
            + File.separator + "download" + File.separator;

    private Context mContext;
    private static AppConfig appConfig;

    public static AppConfig getAppConfig(Context context) {
        if (appConfig == null) {
            appConfig = new AppConfig();
            appConfig.mContext = context;
        }
        return appConfig;
    }

    /**
     * 获取Preference设置
     */
    public static SharedPreferences getSharedPreferences(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context);
    }

    public String get(String key) {
        Properties props = get();
        return (props != null) ? props.getProperty(key) : null;
    }

    public Properties get() {
        FileInputStream fis = null;
        Properties props = new Properties();
        try {
            // 读取files目录下的config
            // fis = activity.openFileInput(APP_CONFIG);

            // 读取app_config目录下的config
            File dirConf = mContext.getDir(APP_CONFIG, Context.MODE_PRIVATE);
            fis = new FileInputStream(dirConf.getPath() + File.separator
                    + APP_CONFIG);

            props.load(fis);
        } catch (Exception e) {
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return props;
    }

    private void setProps(Properties p) {
        FileOutputStream fos = null;
        try {
            // 把config建在files目录下
            // fos = activity.openFileOutput(APP_CONFIG, Context.MODE_PRIVATE);

            // 把config建在(自定义)app_config的目录下
            File dirConf = mContext.getDir(APP_CONFIG, Context.MODE_PRIVATE);
            File conf = new File(dirConf, APP_CONFIG);
            fos = new FileOutputStream(conf);

            p.store(fos, null);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (Exception e) {
            }
        }
    }

    public void set(Properties ps) {
        Properties props = get();
        props.putAll(ps);
        setProps(props);
    }

    public void set(String key, String value) {
        Properties props = get();
        props.setProperty(key, value);
        setProps(props);
    }

    public void remove(String... key) {
        Properties props = get();
        for (String k : key)
            props.remove(k);
        setProps(props);
    }
}

 

 

 

 

 

AppContext .java

package net.oschina.app;

import static net.oschina.app.AppConfig.KEY_FRITST_START;
import static net.oschina.app.AppConfig.KEY_LOAD_IMAGE;
import static net.oschina.app.AppConfig.KEY_TWEET_DRAFT;

import java.util.Properties;
import java.util.UUID;

import net.oschina.app.api.ApiHttpClient;
import net.oschina.app.base.BaseApplication;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.User;
import net.oschina.app.cache.DataCleanManager;
import net.oschina.app.util.CyptoUtils;
import net.oschina.app.util.MethodsCompat;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TLog;
import net.oschina.app.util.UIHelper;

import org.kymjs.kjframe.KJBitmap;
import org.kymjs.kjframe.bitmap.BitmapConfig;
import org.kymjs.kjframe.utils.KJLoger;

import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.PersistentCookieStore;

/**
 * 全局应用程序类:用于保存和调用全局应用配置及访问网络数据
 * 
 * @author 火蚁 (http://my.oschina.net/LittleDY)
 * @version 1.0
 * @created 2014-04-22
 */
public class AppContext extends BaseApplication {

    public static final int PAGE_SIZE = 20;// 默认分页大小

    private static AppContext instance;

    private int loginUid;

    private boolean login;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        init();
        initLogin();
        // Thread.setDefaultUncaughtExceptionHandler(AppException
        // .getAppExceptionHandler(this));
        UIHelper.sendBroadcastForNotice(this);
    }

    private void init() {
        // 初始化网络请求
        AsyncHttpClient client = new AsyncHttpClient();
        PersistentCookieStore myCookieStore = new PersistentCookieStore(this);
        client.setCookieStore(myCookieStore);
        ApiHttpClient.setHttpClient(client);
        ApiHttpClient.setCookie(ApiHttpClient.getCookie(this));

        // Log控制器
        KJLoger.openDebutLog(true);
        TLog.DEBUG = BuildConfig.DEBUG;

        // Bitmap缓存地址
        BitmapConfig.CACHEPATH = "OSChina/imagecache";
    }

    private void initLogin() {
        User user = getLoginUser();
        if (null != user && user.getId() > 0) {
            login = true;
            loginUid = user.getId();
        } else {
            this.cleanLoginInfo();
        }
    }

    /**
     * 获得当前app运行的AppContext
     * 
     * @return
     */
    public static AppContext getInstance() {
        return instance;
    }

    public boolean containsProperty(String key) {
        Properties props = getProperties();
        return props.containsKey(key);
    }

    public void setProperties(Properties ps) {
        AppConfig.getAppConfig(this).set(ps);
    }

    public Properties getProperties() {
        return AppConfig.getAppConfig(this).get();
    }

    public void setProperty(String key, String value) {
        AppConfig.getAppConfig(this).set(key, value);
    }

    /**
     * 获取cookie时传AppConfig.CONF_COOKIE
     * 
     * @param key
     * @return
     */
    public String getProperty(String key) {
        String res = AppConfig.getAppConfig(this).get(key);
        return res;
    }

    public void removeProperty(String... key) {
        AppConfig.getAppConfig(this).remove(key);
    }

    /**
     * 获取App唯一标识
     * 
     * @return
     */
    public String getAppId() {
        String uniqueID = getProperty(AppConfig.CONF_APP_UNIQUEID);
        if (StringUtils.isEmpty(uniqueID)) {
            uniqueID = UUID.randomUUID().toString();
            setProperty(AppConfig.CONF_APP_UNIQUEID, uniqueID);
        }
        return uniqueID;
    }

    /**
     * 获取App安装包信息
     * 
     * @return
     */
    public PackageInfo getPackageInfo() {
        PackageInfo info = null;
        try {
            info = getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (NameNotFoundException e) {
            e.printStackTrace(System.err);
        }
        if (info == null)
            info = new PackageInfo();
        return info;
    }

    /**
     * 保存登录信息
     * 
     * @param username
     * @param pwd
     */
    @SuppressWarnings("serial")
    public void saveUserInfo(final User user) {
        this.loginUid = user.getId();
        this.login = true;
        setProperties(new Properties() {
            {
                setProperty("user.uid", String.valueOf(user.getId()));
                setProperty("user.name", user.getName());
                setProperty("user.face", user.getPortrait());// 用户头像-文件名
                setProperty("user.account", user.getAccount());
                setProperty("user.pwd",
                        CyptoUtils.encode("oschinaApp", user.getPwd()));
                setProperty("user.location", user.getLocation());
                setProperty("user.followers",
                        String.valueOf(user.getFollowers()));
                setProperty("user.fans", String.valueOf(user.getFans()));
                setProperty("user.score", String.valueOf(user.getScore()));
                setProperty("user.favoritecount",
                        String.valueOf(user.getFavoritecount()));
                setProperty("user.gender", String.valueOf(user.getGender()));
                setProperty("user.isRememberMe",
                        String.valueOf(user.isRememberMe()));// 是否记住我的信息
            }
        });
    }

    /**
     * 更新用户信息
     * 
     * @param user
     */
    @SuppressWarnings("serial")
    public void updateUserInfo(final User user) {
        setProperties(new Properties() {
            {
                setProperty("user.name", user.getName());
                setProperty("user.face", user.getPortrait());// 用户头像-文件名
                setProperty("user.followers",
                        String.valueOf(user.getFollowers()));
                setProperty("user.fans", String.valueOf(user.getFans()));
                setProperty("user.score", String.valueOf(user.getScore()));
                setProperty("user.favoritecount",
                        String.valueOf(user.getFavoritecount()));
                setProperty("user.gender", String.valueOf(user.getGender()));
            }
        });
    }

    /**
     * 获得登录用户的信息
     * 
     * @return
     */
    public User getLoginUser() {
        User user = new User();
        user.setId(StringUtils.toInt(getProperty("user.uid"), 0));
        user.setName(getProperty("user.name"));
        user.setPortrait(getProperty("user.face"));
        user.setAccount(getProperty("user.account"));
        user.setLocation(getProperty("user.location"));
        user.setFollowers(StringUtils.toInt(getProperty("user.followers"), 0));
        user.setFans(StringUtils.toInt(getProperty("user.fans"), 0));
        user.setScore(StringUtils.toInt(getProperty("user.score"), 0));
        user.setFavoritecount(StringUtils.toInt(
                getProperty("user.favoritecount"), 0));
        user.setRememberMe(StringUtils.toBool(getProperty("user.isRememberMe")));
        user.setGender(getProperty("user.gender"));
        return user;
    }

    /**
     * 清除登录信息
     */
    public void cleanLoginInfo() {
        this.loginUid = 0;
        this.login = false;
        removeProperty("user.uid", "user.name", "user.face", "user.location",
                "user.followers", "user.fans", "user.score",
                "user.isRememberMe", "user.gender", "user.favoritecount");
    }

    public int getLoginUid() {
        return loginUid;
    }

    public boolean isLogin() {
        return login;
    }

    /**
     * 用户注销
     */
    public void Logout() {
        cleanLoginInfo();
        ApiHttpClient.cleanCookie();
        this.cleanCookie();
        this.login = false;
        this.loginUid = 0;

        Intent intent = new Intent(Constants.INTENT_ACTION_LOGOUT);
        sendBroadcast(intent);
    }

    /**
     * 清除保存的缓存
     */
    public void cleanCookie() {
        removeProperty(AppConfig.CONF_COOKIE);
    }

    /**
     * 清除app缓存
     */
    public void clearAppCache() {
        DataCleanManager.cleanDatabases(this);
        // 清除数据缓存
        DataCleanManager.cleanInternalCache(this);
        // 2.2版本才有将应用缓存转移到sd卡的功能
        if (isMethodsCompat(android.os.Build.VERSION_CODES.FROYO)) {
            DataCleanManager.cleanCustomCache(MethodsCompat
                    .getExternalCacheDir(this));
        }
        // 清除编辑器保存的临时内容
        Properties props = getProperties();
        for (Object key : props.keySet()) {
            String _key = key.toString();
            if (_key.startsWith("temp"))
                removeProperty(_key);
        }
        new KJBitmap().cleanCache();
    }

    public static void setLoadImage(boolean flag) {
        set(KEY_LOAD_IMAGE, flag);
    }

    /**
     * 判断当前版本是否兼容目标版本的方法
     * 
     * @param VersionCode
     * @return
     */
    public static boolean isMethodsCompat(int VersionCode) {
        int currentVersion = android.os.Build.VERSION.SDK_INT;
        return currentVersion >= VersionCode;
    }

    public static String getTweetDraft() {
        return getPreferences().getString(
                KEY_TWEET_DRAFT + getInstance().getLoginUid(), "");
    }

    public static void setTweetDraft(String draft) {
        set(KEY_TWEET_DRAFT + getInstance().getLoginUid(), draft);
    }

    public static String getNoteDraft() {
        return getPreferences().getString(
                AppConfig.KEY_NOTE_DRAFT + getInstance().getLoginUid(), "");
    }

    public static void setNoteDraft(String draft) {
        set(AppConfig.KEY_NOTE_DRAFT + getInstance().getLoginUid(), draft);
    }

    public static boolean isFristStart() {
        return getPreferences().getBoolean(KEY_FRITST_START, true);
    }

    public static void setFristStart(boolean frist) {
        set(KEY_FRITST_START, frist);
    }
}

 

 

 

 

 

 

 

 

AppException.java

package net.oschina.app;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.UnknownHostException;

import net.oschina.app.util.UIHelper;

import org.apache.http.HttpException;
import org.kymjs.kjframe.utils.FileUtils;
import org.kymjs.kjframe.utils.SystemTool;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Looper;

/**
 * 应用程序异常:用于捕获异常和提示错误信息
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @author kymjs (kymjs123@gmali.com)
 * @created 2014年9月25日 下午5:34:05
 * 
 */
@SuppressWarnings("serial")
public class AppException extends Exception implements UncaughtExceptionHandler {

    /** 定义异常类型 */
    public final static byte TYPE_NETWORK = 0x01;
    public final static byte TYPE_SOCKET = 0x02;
    public final static byte TYPE_HTTP_CODE = 0x03;
    public final static byte TYPE_HTTP_ERROR = 0x04;
    public final static byte TYPE_XML = 0x05;
    public final static byte TYPE_IO = 0x06;
    public final static byte TYPE_RUN = 0x07;
    public final static byte TYPE_JSON = 0x08;
    public final static byte TYPE_FILENOTFOUND = 0x09;

    private byte type;// 异常的类型
    // 异常的状态码,这里一般是网络请求的状态码
    private int code;

    /** 系统默认的UncaughtException处理类 */
    private AppContext mContext;

    private AppException(Context context) {
        this.mContext = (AppContext) context;
    }

    private AppException(byte type, int code, Exception excp) {
        super(excp);
        this.type = type;
        this.code = code;
    }

    public int getCode() {
        return this.code;
    }

    public int getType() {
        return this.type;
    }

    public static AppException http(int code) {
        return new AppException(TYPE_HTTP_CODE, code, null);
    }

    public static AppException http(Exception e) {
        return new AppException(TYPE_HTTP_ERROR, 0, e);
    }

    public static AppException socket(Exception e) {
        return new AppException(TYPE_SOCKET, 0, e);
    }

    public static AppException file(Exception e) {
        return new AppException(TYPE_FILENOTFOUND, 0, e);
    }

    // io异常
    public static AppException io(Exception e) {
        return io(e, 0);
    }

    // io异常
    public static AppException io(Exception e, int code) {
        if (e instanceof UnknownHostException || e instanceof ConnectException) {
            return new AppException(TYPE_NETWORK, code, e);
        } else if (e instanceof IOException) {
            return new AppException(TYPE_IO, code, e);
        }
        return run(e);
    }

    public static AppException xml(Exception e) {
        return new AppException(TYPE_XML, 0, e);
    }

    public static AppException json(Exception e) {
        return new AppException(TYPE_JSON, 0, e);
    }

    // 网络请求异常
    public static AppException network(Exception e) {
        if (e instanceof UnknownHostException || e instanceof ConnectException) {
            return new AppException(TYPE_NETWORK, 0, e);
        } else if (e instanceof HttpException) {
            return http(e);
        } else if (e instanceof SocketException) {
            return socket(e);
        }
        return http(e);
    }

    public static AppException run(Exception e) {
        return new AppException(TYPE_RUN, 0, e);
    }

    /**
     * 获取APP异常崩溃处理对象
     * 
     * @param context
     * @return
     */
    public static AppException getAppExceptionHandler(Context context) {
        return new AppException(context.getApplicationContext());
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex)) {
            System.exit(0);
        }
    }

    /**
     * 自定义异常处理:收集错误信息&发送错误报告
     * 
     * @param ex
     * @return true:处理了该异常信息;否则返回false
     */
    private boolean handleException(final Throwable ex) {
        if (ex == null || mContext == null) {
            return false;
        }
        boolean success = true;
        try {
            success = saveToSDCard(ex);
        } catch (Exception e) {
        } finally {
            if (!success) {
                return false;
            } else {
                final Context context = AppManager.getAppManager()
                        .currentActivity();
                // 显示异常信息&发送报告
                new Thread() {
                    @Override
                    public void run() {
                        Looper.prepare();
                        // 拿到未捕获的异常,
                        UIHelper.sendAppCrashReport(context);
                        Looper.loop();
                    }
                }.start();
            }
        }
        return true;
    }

    private boolean saveToSDCard(Throwable ex) throws Exception {
        boolean append = false;
        File file = FileUtils.getSaveFile("OSChina", "OSCLog.log");
        if (System.currentTimeMillis() - file.lastModified() > 5000) {
            append = true;
        }
        PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(
                file, append)));
        // 导出发生异常的时间
        pw.println(SystemTool.getDataTime("yyyy-MM-dd-HH-mm-ss"));
        // 导出手机信息
        dumpPhoneInfo(pw);
        pw.println();
        // 导出异常的调用栈信息
        ex.printStackTrace(pw);
        pw.println();
        pw.close();
        return append;
    }

    private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {
        // 应用的版本名称和版本号
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(),
                PackageManager.GET_ACTIVITIES);
        pw.print("App Version: ");
        pw.print(pi.versionName);
        pw.print('_');
        pw.println(pi.versionCode);
        pw.println();

        // android版本号
        pw.print("OS Version: ");
        pw.print(Build.VERSION.RELEASE);
        pw.print("_");
        pw.println(Build.VERSION.SDK_INT);
        pw.println();

        // 手机制造商
        pw.print("Vendor: ");
        pw.println(Build.MANUFACTURER);
        pw.println();

        // 手机型号
        pw.print("Model: ");
        pw.println(Build.MODEL);
        pw.println();

        // cpu架构
        pw.print("CPU ABI: ");
        pw.println(Build.CPU_ABI);
        pw.println();
    }
}

 

 

 

 

 

 

AppManager.java

package net.oschina.app;

import java.util.Stack;

import android.app.Activity;
import android.content.Context;

/**
 * activity堆栈式管理
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年10月30日 下午6:22:05
 * 
 */
public class AppManager {

    private static Stack<Activity> activityStack;
    private static AppManager instance;

    private AppManager() {}

    /**
     * 单一实例
     */
    public static AppManager getAppManager() {
        if (instance == null) {
            instance = new AppManager();
        }
        return instance;
    }

    /**
     * 添加Activity到堆栈
     */
    public void addActivity(Activity activity) {
        if (activityStack == null) {
            activityStack = new Stack<Activity>();
        }
        activityStack.add(activity);
    }

    /**
     * 获取当前Activity(堆栈中最后一个压入的)
     */
    public Activity currentActivity() {
        Activity activity = activityStack.lastElement();
        return activity;
    }

    /**
     * 结束当前Activity(堆栈中最后一个压入的)
     */
    public void finishActivity() {
        Activity activity = activityStack.lastElement();
        finishActivity(activity);
    }

    /**
     * 结束指定的Activity
     */
    public void finishActivity(Activity activity) {
        if (activity != null && !activity.isFinishing()) {
            activityStack.remove(activity);
            activity.finish();
            activity = null;
        }
    }

    /**
     * 结束指定类名的Activity
     */
    public void finishActivity(Class<?> cls) {
        for (Activity activity : activityStack) {
            if (activity.getClass().equals(cls)) {
                finishActivity(activity);
                break;
            }
        }
    }

    /**
     * 结束所有Activity
     */
    public void finishAllActivity() {
        for (int i = 0, size = activityStack.size(); i < size; i++) {
            if (null != activityStack.get(i)) {
                finishActivity(activityStack.get(i));
                break;
            }
        }
        activityStack.clear();
    }

    /**
     * 获取指定的Activity
     * 
     * @author kymjs
     */
    public static Activity getActivity(Class<?> cls) {
        if (activityStack != null)
            for (Activity activity : activityStack) {
                if (activity.getClass().equals(cls)) {
                    return activity;
                }
            }
        return null;
    }

    /**
     * 退出应用程序
     */
    public void AppExit(Context context) {
        try {
            finishAllActivity();
            // 杀死该应用进程
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(0);
        } catch (Exception e) {
        }
    }
}

 

 

 

 

 

AppStart.java

package net.oschina.app;

import java.io.File;

import net.oschina.app.ui.MainActivity;
import net.oschina.app.util.TDevice;

import org.kymjs.kjframe.http.KJAsyncTask;
import org.kymjs.kjframe.utils.FileUtils;
import org.kymjs.kjframe.utils.PreferenceHelper;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;

/**
 * 应用启动界面
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年12月22日 上午11:51:56
 * 
 */
public class AppStart extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 防止第三方跳转时出现双实例
        Activity aty = AppManager.getActivity(MainActivity.class);
        if (aty != null && !aty.isFinishing()) {
            finish();
        }
        // SystemTool.gc(this); //针对性能好的手机使用,加快应用相应速度

        final View view = View.inflate(this, R.layout.app_start, null);
        setContentView(view);
        // 渐变展示启动屏
        AlphaAnimation aa = new AlphaAnimation(0.5f, 1.0f);
        aa.setDuration(800);
        view.startAnimation(aa);
        aa.setAnimationListener(new AnimationListener() {
            @Override
            public void onAnimationEnd(Animation arg0) {
                redirectTo();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}

            @Override
            public void onAnimationStart(Animation animation) {}
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        int cacheVersion = PreferenceHelper.readInt(this, "first_install",
                "first_install", -1);
        int currentVersion = TDevice.getVersionCode();
        if (cacheVersion < currentVersion) {
            PreferenceHelper.write(this, "first_install", "first_install",
                    currentVersion);
            cleanImageCache();
        }
    }

    private void cleanImageCache() {
        final File folder = FileUtils.getSaveFolder("OSChina/imagecache");
        KJAsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                for (File file : folder.listFiles()) {
                    file.delete();
                }
            }
        });
    }

    /**
     * 跳转到...
     */
    private void redirectTo() {
        Intent uploadLog = new Intent(this, LogUploadService.class);
        startService(uploadLog);
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

 

 

 

 

 

LogUploadService.java

package net.oschina.app;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.util.StringUtils;

import org.apache.http.Header;
import org.kymjs.kjframe.utils.FileUtils;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.loopj.android.http.AsyncHttpResponseHandler;

public class LogUploadService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        final File log = FileUtils.getSaveFile("OSChina", "OSCLog.log");
        String data = null;
        try {
            FileInputStream inputStream = new FileInputStream(log);
            data = StringUtils.toConvertString(inputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (!StringUtils.isEmpty(data)) {
            OSChinaApi.uploadLog(data, new AsyncHttpResponseHandler() {
                @Override
                public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
                    log.delete();
                    LogUploadService.this.stopSelf();
                }

                @Override
                public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                        Throwable arg3) {
                    LogUploadService.this.stopSelf();
                }
            });
        } else {
            LogUploadService.this.stopSelf();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}

 

 

 

 

 

 

 

ActiveAdapter.java

package net.oschina.app.adapter;

import net.oschina.app.R;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.bean.Active;
import net.oschina.app.bean.Active.ObjectReply;
import net.oschina.app.bean.Tweet;
import net.oschina.app.emoji.InputHelper;
import net.oschina.app.ui.ImagePreviewActivity;
import net.oschina.app.util.ImageUtils;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.UIHelper;
import net.oschina.app.widget.AvatarView;
import net.oschina.app.widget.MyLinkMovementMethod;
import net.oschina.app.widget.MyURLSpan;
import net.oschina.app.widget.TweetTextView;

import org.kymjs.kjframe.KJBitmap;
import org.kymjs.kjframe.bitmap.BitmapCallBack;
import org.kymjs.kjframe.bitmap.BitmapHelper;
import org.kymjs.kjframe.utils.DensityUtils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

public class ActiveAdapter extends ListBaseAdapter {
    private final static String AT_HOST_PRE = "http://my.oschina.net";
    private final static String MAIN_HOST = "http://www.oschina.net";

    public ActiveAdapter() {}

    private Bitmap recordBitmap;
    private final KJBitmap kjb = new KJBitmap();
    private int rectSize;

    private void initRecordImg(Context cxt) {
        recordBitmap = BitmapFactory.decodeResource(cxt.getResources(),
                R.drawable.audio3);
        recordBitmap = ImageUtils.zoomBitmap(recordBitmap,
                DensityUtils.dip2px(cxt, 20f), DensityUtils.dip2px(cxt, 20f));
    }

    private void initImageSize(Context cxt) {
        if (cxt != null && rectSize == 0) {
            rectSize = (int) cxt.getResources().getDimension(R.dimen.space_100);
        } else {
            rectSize = 300;
        }
    }

    @Override
    @SuppressLint("InflateParams")
    protected View getRealView(int position, View convertView,
            final ViewGroup parent) {
        ViewHolder vh = null;
        initImageSize(parent.getContext());
        if (convertView == null || convertView.getTag() == null) {
            convertView = getLayoutInflater(parent.getContext()).inflate(
                    R.layout.list_cell_active, null);
            vh = new ViewHolder(convertView);
            convertView.setTag(vh);
        } else {
            vh = (ViewHolder) convertView.getTag();
        }

        final Active item = (Active) mDatas.get(position);

        vh.name.setText(item.getAuthor());

        vh.action.setText(UIHelper.parseActiveAction(item.getObjectType(),
                item.getObjectCatalog(), item.getObjectTitle()));

        if (TextUtils.isEmpty(item.getMessage())) {
            vh.body.setVisibility(View.GONE);
        } else {
            vh.body.setMovementMethod(MyLinkMovementMethod.a());
            vh.body.setFocusable(false);
            vh.body.setDispatchToParent(true);
            vh.body.setLongClickable(false);

            Spanned span = Html.fromHtml(modifyPath(item.getMessage()));

            if (!StringUtils.isEmpty(item.getTweetattach())) {
                if (recordBitmap == null) {
                    initRecordImg(parent.getContext());
                }
                ImageSpan recordImg = new ImageSpan(parent.getContext(),
                        recordBitmap);
                SpannableString str = new SpannableString("c");
                str.setSpan(recordImg, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                vh.body.setText(str);
                span = InputHelper.displayEmoji(parent.getContext()
                        .getResources(), span);
                vh.body.append(span);
            } else {
                span = InputHelper.displayEmoji(parent.getContext()
                        .getResources(), span);
                vh.body.setText(span);
            }
            MyURLSpan.parseLinkText(vh.body, span);
        }

        ObjectReply reply = item.getObjectReply();
        if (reply != null) {
            vh.reply.setMovementMethod(MyLinkMovementMethod.a());
            vh.reply.setFocusable(false);
            vh.reply.setDispatchToParent(true);
            vh.reply.setLongClickable(false);
            Spanned span = UIHelper.parseActiveReply(reply.objectName,
                    reply.objectBody);
            vh.reply.setText(span);//
            MyURLSpan.parseLinkText(vh.reply, span);
            vh.lyReply.setVisibility(TextView.VISIBLE);
        } else {
            vh.reply.setText("");
            vh.lyReply.setVisibility(TextView.GONE);
        }

        vh.time.setText(StringUtils.friendly_time(item.getPubDate()));

        vh.from.setVisibility(View.VISIBLE);
        switch (item.getAppClient()) {
        default:
            vh.from.setText(R.string.from_web); // 不显示
            vh.from.setVisibility(View.GONE);
            break;
        case Tweet.CLIENT_MOBILE:
            vh.from.setText(R.string.from_mobile);
            break;
        case Tweet.CLIENT_ANDROID:
            vh.from.setText(R.string.from_android);
            break;
        case Tweet.CLIENT_IPHONE:
            vh.from.setText(R.string.from_iphone);
            break;
        case Tweet.CLIENT_WINDOWS_PHONE:
            vh.from.setText(R.string.from_windows_phone);
            break;
        case Tweet.CLIENT_WECHAT:
            vh.from.setText(R.string.from_wechat);
            break;
        }

        if (item.getCommentCount() > 0) {
            vh.commentCount.setText(String.valueOf(item.getCommentCount()));
            vh.commentCount.setVisibility(View.VISIBLE);
        } else {
            vh.commentCount.setVisibility(View.GONE);
        }

        vh.avatar.setUserInfo(item.getAuthorId(), item.getAuthor());
        vh.avatar.setAvatarUrl(item.getPortrait());

        if (!TextUtils.isEmpty(item.getTweetimage())) {
            setTweetImage(parent, vh, item);
        } else {
            vh.pic.setVisibility(View.GONE);
            vh.pic.setImageBitmap(null);
        }

        return convertView;
    }

    /**
     * 动态设置图片显示样式
     * 
     * @author kymjs
     */
    private void setTweetImage(final ViewGroup parent, final ViewHolder vh,
            final Active item) {
        vh.pic.setVisibility(View.VISIBLE);

        kjb.display(vh.pic, item.getTweetimage(), R.drawable.pic_bg, rectSize,
                rectSize, new BitmapCallBack() {
                    @Override
                    public void onSuccess(Bitmap bitmap) {
                        super.onSuccess(bitmap);
                        if (bitmap != null) {
                            bitmap = BitmapHelper.scaleWithXY(bitmap, rectSize
                                    / bitmap.getHeight());
                            vh.pic.setImageBitmap(bitmap);
                        }
                    }
                });

        vh.pic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ImagePreviewActivity.showImagePrivew(parent.getContext(), 0,
                        new String[] { getOriginalUrl(item.getTweetimage()) });
            }
        });
    }

    private String modifyPath(String message) {
        message = message.replaceAll("(<a[^>]+href=\")/([\\S]+)\"", "$1"
                + AT_HOST_PRE + "/$2\"");
        message = message.replaceAll(
                "(<a[^>]+href=\")http://m.oschina.net([\\S]+)\"", "$1"
                        + MAIN_HOST + "$2\"");
        return message;
    }

    private String getOriginalUrl(String url) {
        return url.replaceAll("_thumb", "");
    }

    static class ViewHolder {
        @InjectView(R.id.tv_name)
        TextView name;
        @InjectView(R.id.tv_from)
        TextView from;
        @InjectView(R.id.tv_time)
        TextView time;
        @InjectView(R.id.tv_action)
        TextView action;
        @InjectView(R.id.tv_action_name)
        TextView actionName;
        @InjectView(R.id.tv_comment_count)
        TextView commentCount;
        // @InjectView(R.id.tv_reply_content)
        // TextView retweetCount;
        @InjectView(R.id.tv_body)
        TweetTextView body;
        @InjectView(R.id.tv_reply)
        TweetTextView reply;
        @InjectView(R.id.iv_pic)
        ImageView pic;
        @InjectView(R.id.ly_reply)
        View lyReply;
        @InjectView(R.id.iv_avatar)
        AvatarView avatar;

        public ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }
}

 

 

 

 

 

 

BlogAdapter.java

package net.oschina.app.adapter;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.bean.Blog;
import net.oschina.app.bean.BlogList;
import net.oschina.app.util.StringUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

/**
 * @author HuangWenwei
 * 
 * @date 2014年9月29日
 */
public class BlogAdapter extends ListBaseAdapter<Blog> {

    static class ViewHolder {

        @InjectView(R.id.tv_title)
        TextView title;
        @InjectView(R.id.tv_description)
        TextView description;
        @InjectView(R.id.tv_source)
        TextView source;
        @InjectView(R.id.tv_time)
        TextView time;
        @InjectView(R.id.tv_comment_count)
        TextView comment_count;
        @InjectView(R.id.iv_tip)
        ImageView tip;

        public ViewHolder(View view) {
            ButterKnife.inject(this, view);
        }
    }

    @Override
    protected View getRealView(int position, View convertView, ViewGroup parent) {
        ViewHolder vh = null;
        if (convertView == null || convertView.getTag() == null) {
            convertView = getLayoutInflater(parent.getContext()).inflate(
                    R.layout.list_cell_news, null);
            vh = new ViewHolder(convertView);
            convertView.setTag(vh);
        } else {
            vh = (ViewHolder) convertView.getTag();
        }

        Blog blog = mDatas.get(position);

        vh.tip.setVisibility(View.VISIBLE);
        if (blog.getDocumenttype() == Blog.DOC_TYPE_ORIGINAL) {
            vh.tip.setImageResource(R.drawable.widget_original_icon);
        } else {
            vh.tip.setImageResource(R.drawable.widget_repaste_icon);
        }

        vh.title.setText(blog.getTitle());

        if (AppContext.isOnReadedPostList(BlogList.PREF_READED_BLOG_LIST,
                blog.getId() + "")) {
            vh.title.setTextColor(parent.getContext().getResources()
                    .getColor(R.color.main_gray));
        } else {
            vh.title.setTextColor(parent.getContext().getResources()
                    .getColor(R.color.main_black));
        }

        vh.description.setVisibility(View.GONE);
        String description = blog.getBody();
        if (null != description && !StringUtils.isEmpty(description)) {
            vh.description.setVisibility(View.VISIBLE);
            vh.description.setText(description.trim());
        }

        vh.source.setText(blog.getAuthor());
        vh.time.setText(StringUtils.friendly_time(blog.getPubDate()));
        vh.comment_count.setText(blog.getCommentCount() + "");
        return convertView;
    }
}

 

 

 

 

 

 

RecycleBin.java

package net.oschina.app.adapter;

import android.annotation.SuppressLint;
import android.os.Build;
import android.util.SparseArray;
import android.view.View;

/**
 * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
 * storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
 * start of a layout. By construction, they are displaying current information. At the end of
 * layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
 * could potentially be used by the adapter to avoid allocating views unnecessarily.
 * <p>
 * This class was taken from Android's implementation of {@link android.widget.AbsListView} which
 * is copyrighted 2006 The Android Open Source Project.
 */
public class RecycleBin {
  /**
   * Views that were on screen at the start of layout. This array is populated at the start of
   * layout, and at the end of layout all view in activeViews are moved to scrapViews.
   * Views in activeViews represent a contiguous range of Views, with position of the first
   * view store in mFirstActivePosition.
   */
  private View[] activeViews = new View[0];
  private int[] activeViewTypes = new int[0];

  /** Unsorted views that can be used by the adapter as a convert view. */
  private SparseArray<View>[] scrapViews;

  private int viewTypeCount;

  private SparseArray<View> currentScrapViews;

  public void setViewTypeCount(int viewTypeCount) {
    if (viewTypeCount < 1) {
      throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
    }
    //noinspection unchecked
    SparseArray<View>[] scrapViews = new SparseArray[viewTypeCount];
    for (int i = 0; i < viewTypeCount; i++) {
      scrapViews[i] = new SparseArray<View>();
    }
    this.viewTypeCount = viewTypeCount;
    currentScrapViews = scrapViews[0];
    this.scrapViews = scrapViews;
  }

  protected boolean shouldRecycleViewType(int viewType) {
    return viewType >= 0;
  }

  /** @return A view from the ScrapViews collection. These are unordered. */
  View getScrapView(int position, int viewType) {
    if (viewTypeCount == 1) {
      return retrieveFromScrap(currentScrapViews, position);
    } else if (viewType >= 0 && viewType < scrapViews.length) {
      return retrieveFromScrap(scrapViews[viewType], position);
    }
    return null;
  }

  /**
   * Put a view into the ScrapViews list. These views are unordered.
   *
   * @param scrap The view to add
   */
  @SuppressLint("NewApi")
void addScrapView(View scrap, int position, int viewType) {
    if (viewTypeCount == 1) {
      currentScrapViews.put(position, scrap);
    } else {
      scrapViews[viewType].put(position, scrap);
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
      scrap.setAccessibilityDelegate(null);
    }
  }

  /** Move all views remaining in activeViews to scrapViews. */
  @SuppressLint("NewApi")
void scrapActiveViews() {
    final View[] activeViews = this.activeViews;
    final int[] activeViewTypes = this.activeViewTypes;
    final boolean multipleScraps = viewTypeCount > 1;

    SparseArray<View> scrapViews = currentScrapViews;
    final int count = activeViews.length;
    for (int i = count - 1; i >= 0; i--) {
      final View victim = activeViews[i];
      if (victim != null) {
        int whichScrap = activeViewTypes[i];

        activeViews[i] = null;
        activeViewTypes[i] = -1;

        if (!shouldRecycleViewType(whichScrap)) {
          continue;
        }

        if (multipleScraps) {
          scrapViews = this.scrapViews[whichScrap];
        }
        scrapViews.put(i, victim);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
          victim.setAccessibilityDelegate(null);
        }
      }
    }

    pruneScrapViews();
  }

  /**
   * Makes sure that the size of scrapViews does not exceed the size of activeViews.
   * (This can happen if an adapter does not recycle its views).
   */
  private void pruneScrapViews() {
    final int maxViews = activeViews.length;
    final int viewTypeCount = this.viewTypeCount;
    final SparseArray<View>[] scrapViews = this.scrapViews;
    for (int i = 0; i < viewTypeCount; ++i) {
      final SparseArray<View> scrapPile = scrapViews[i];
      int size = scrapPile.size();
      final int extras = size - maxViews;
      size--;
      for (int j = 0; j < extras; j++) {
        scrapPile.remove(scrapPile.keyAt(size--));
      }
    }
  }

  static View retrieveFromScrap(SparseArray<View> scrapViews, int position) {
    int size = scrapViews.size();
    if (size > 0) {
      // See if we still have a view for this position.
      for (int i = 0; i < size; i++) {
        int fromPosition = scrapViews.keyAt(i);
        View view = scrapViews.get(fromPosition);
        if (fromPosition == position) {
          scrapViews.remove(fromPosition);
          return view;
        }
      }
      int index = size - 1;
      View r = scrapViews.valueAt(index);
      scrapViews.remove(scrapViews.keyAt(index));
      return r;
    } else {
      return null;
    }
  }
}

 

 

 

 

 

 

ViewPageFragmentAdapter.java

package net.oschina.app.adapter;

import java.util.ArrayList;

import net.oschina.app.R;
import net.oschina.app.widget.PagerSlidingTabStrip;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

@SuppressLint("Recycle")
public class ViewPageFragmentAdapter extends FragmentStatePagerAdapter {

    private final Context mContext;
    protected PagerSlidingTabStrip mPagerStrip;
    private final ViewPager mViewPager;
    private final ArrayList<ViewPageInfo> mTabs = new ArrayList<ViewPageInfo>();

    public ViewPageFragmentAdapter(FragmentManager fm,
            PagerSlidingTabStrip pageStrip, ViewPager pager) {
        super(fm);
        mContext = pager.getContext();
        mPagerStrip = pageStrip;
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mPagerStrip.setViewPager(mViewPager);
    }

    public void addTab(String title, String tag, Class<?> clss, Bundle args) {
        ViewPageInfo viewPageInfo = new ViewPageInfo(title, tag, clss, args);
        addFragment(viewPageInfo);
    }

    public void addAllTab(ArrayList<ViewPageInfo> mTabs) {
        for (ViewPageInfo viewPageInfo : mTabs) {
            addFragment(viewPageInfo);
        }
    }

    private void addFragment(ViewPageInfo info) {
        if (info == null) {
            return;
        }

        // 加入tab title
        View v = LayoutInflater.from(mContext).inflate(
                R.layout.base_viewpage_fragment_tab_item, null, false);
        TextView title = (TextView) v.findViewById(R.id.tab_title);
        title.setText(info.title);
        mPagerStrip.addTab(v);

        mTabs.add(info);
        notifyDataSetChanged();
    }

    /**
     * 移除第一次
     */
    public void remove() {
        remove(0);
    }

    /**
     * 移除一个tab
     * 
     * @param index
     *            备注:如果index小于0,则从第一个开始删 如果大于tab的数量值则从最后一个开始删除
     */
    public void remove(int index) {
        if (mTabs.isEmpty()) {
            return;
        }
        if (index < 0) {
            index = 0;
        }
        if (index >= mTabs.size()) {
            index = mTabs.size() - 1;
        }
        mTabs.remove(index);
        mPagerStrip.removeTab(index, 1);
        notifyDataSetChanged();
    }

    /**
     * 移除所有的tab
     */
    public void removeAll() {
        if (mTabs.isEmpty()) {
            return;
        }
        mPagerStrip.removeAllTab();
        mTabs.clear();
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mTabs.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;
    }

    @Override
    public Fragment getItem(int position) {
        ViewPageInfo info = mTabs.get(position);
        return Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mTabs.get(position).title;
    }
}

 

 

 

 

 

 

 

 

 

 

ApiClientHelper.java

package net.oschina.app.api;

import net.oschina.app.AppContext;

public class ApiClientHelper {
	
	/**
	 * 获得请求的服务端数据的userAgent
	 * @param appContext
	 * @return
	 */
	public static String getUserAgent(AppContext appContext) {
		StringBuilder ua = new StringBuilder("OSChina.NET");
		ua.append('/' + appContext.getPackageInfo().versionName + '_'
				+  appContext.getPackageInfo().versionCode);// app版本信息
		ua.append("/Android");// 手机系统平台
		ua.append("/" + android.os.Build.VERSION.RELEASE);// 手机系统版本
		ua.append("/" + android.os.Build.MODEL); // 手机型号
		ua.append("/" + appContext.getAppId());// 客户端唯一标识
		return ua.toString();
	}
}

 

 

 

 

 

 

ApiHttpClient.java

package net.oschina.app.api;

import java.util.Locale;

import net.oschina.app.AppContext;
import net.oschina.app.util.TLog;

import org.apache.http.client.params.ClientPNames;

import android.content.Context;
import android.util.Log;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

public class ApiHttpClient {

    public final static String HOST = "www.oschina.net";
    private static String API_URL = "http://www.oschina.net/%s";
    // public final static String HOST = "192.168.1.46";
    // private static String API_URL = "http://192.168.1.46/%s";
    public static final String DELETE = "DELETE";
    public static final String GET = "GET";
    public static final String POST = "POST";
    public static final String PUT = "PUT";
    public static AsyncHttpClient client;

    public ApiHttpClient() {}

    public static AsyncHttpClient getHttpClient() {
        return client;
    }

    public static void cancelAll(Context context) {
        client.cancelRequests(context, true);
    }

    public static void clearUserCookies(Context context) {
        // (new HttpClientCookieStore(context)).a();
    }

    public static void delete(String partUrl, AsyncHttpResponseHandler handler) {
        client.delete(getAbsoluteApiUrl(partUrl), handler);
        log(new StringBuilder("DELETE ").append(partUrl).toString());
    }

    public static void get(String partUrl, AsyncHttpResponseHandler handler) {
        client.get(getAbsoluteApiUrl(partUrl), handler);
        log(new StringBuilder("GET ").append(partUrl).toString());
    }

    public static void get(String partUrl, RequestParams params,
            AsyncHttpResponseHandler handler) {
        client.get(getAbsoluteApiUrl(partUrl), params, handler);
        log(new StringBuilder("GET ").append(partUrl).append("&")
                .append(params).toString());
    }

    public static String getAbsoluteApiUrl(String partUrl) {
        String url = String.format(API_URL, partUrl);
        Log.d("BASE_CLIENT", "request:" + url);
        return url;
    }

    public static String getApiUrl() {
        return API_URL;
    }

    public static void getDirect(String url, AsyncHttpResponseHandler handler) {
        client.get(url, handler);
        log(new StringBuilder("GET ").append(url).toString());
    }

    public static void log(String log) {
        Log.d("BaseApi", log);
        TLog.log("Test", log);
    }

    public static void post(String partUrl, AsyncHttpResponseHandler handler) {
        client.post(getAbsoluteApiUrl(partUrl), handler);
        log(new StringBuilder("POST ").append(partUrl).toString());
    }

    public static void post(String partUrl, RequestParams params,
            AsyncHttpResponseHandler handler) {
        client.post(getAbsoluteApiUrl(partUrl), params, handler);
        log(new StringBuilder("POST ").append(partUrl).append("&")
                .append(params).toString());
    }

    public static void postDirect(String url, RequestParams params,
            AsyncHttpResponseHandler handler) {
        client.post(url, params, handler);
        log(new StringBuilder("POST ").append(url).append("&").append(params)
                .toString());
    }

    public static void put(String partUrl, AsyncHttpResponseHandler handler) {
        client.put(getAbsoluteApiUrl(partUrl), handler);
        log(new StringBuilder("PUT ").append(partUrl).toString());
    }

    public static void put(String partUrl, RequestParams params,
            AsyncHttpResponseHandler handler) {
        client.put(getAbsoluteApiUrl(partUrl), params, handler);
        log(new StringBuilder("PUT ").append(partUrl).append("&")
                .append(params).toString());
    }

    public static void setApiUrl(String apiUrl) {
        API_URL = apiUrl;
    }

    public static void setHttpClient(AsyncHttpClient c) {
        client = c;
        client.addHeader("Accept-Language", Locale.getDefault().toString());
        client.addHeader("Host", HOST);
        client.addHeader("Connection", "Keep-Alive");
        client.getHttpClient().getParams()
                .setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);

        setUserAgent(ApiClientHelper.getUserAgent(AppContext.getInstance()));
    }

    public static void setUserAgent(String userAgent) {
        client.setUserAgent(userAgent);
    }

    public static void setCookie(String cookie) {
        client.addHeader("Cookie", cookie);
    }

    private static String appCookie;

    public static void cleanCookie() {
        appCookie = "";
    }

    public static String getCookie(AppContext appContext) {
        if (appCookie == null || appCookie == "") {
            appCookie = appContext.getProperty("cookie");
        }
        return appCookie;
    }
}

 

 

 

 

 

 

 

 

ApiResponse.java

package net.oschina.app.api;

import org.json.JSONObject;

public class ApiResponse {
    protected Object _data;
    protected String _message;
    protected int _errorCode;
    protected boolean _isOk;
    private long _total;
    private String _serverTime;
    private boolean isCanceled;

    public ApiResponse(JSONObject json) {
	if (json != null) {
	    setData(json.optJSONObject("data") == null ? json
		    .optJSONArray("data") : json.optJSONObject("data"));
	    setMessage(json.optString("result_desc"));
	    setErrorCode(json.optInt("result_code"));
	    setOk(getErrorCode() == 0);
	    setServerTime(json.optString("timestamp"));
	}
    }

    public Object getData() {
	return _data;
    }

    public void setData(Object _data) {
	this._data = _data;
    }

    public boolean isOk() {
	return _isOk;
    }

    public void setOk(boolean _isOk) {
	this._isOk = _isOk;
    }

    public String getMessage() {
	return _message;
    }

    public void setMessage(String _message) {
	this._message = _message;
    }

    public int getErrorCode() {
	return _errorCode;
    }

    public void setErrorCode(int _errorCode) {
	this._errorCode = _errorCode;
    }

    @Override
    public String toString() {
	return "data:" + getData() + " message:" + getMessage() + " errocode:"
		+ _errorCode;
    }

    public void update(ApiResponse response) {
	_message = response.getMessage();
    }

    public void setTotal(long total) {
	_total = total;
    }

    public long getTotal() {
	return _total;
    }

    public String getServerTime() {
	return _serverTime;
    }

    public void setServerTime(String _serverTime) {
	this._serverTime = _serverTime;
    }

    public boolean isCanceled() {
	return isCanceled;
    }

    public void setCanceled(boolean isCanceled) {
	this.isCanceled = isCanceled;
    }
}

 

 

 

 

 

 

OperationResponseHandler.java

package net.oschina.app.api;

import java.io.ByteArrayInputStream;

import org.apache.http.Header;

import android.os.Looper;

import com.loopj.android.http.AsyncHttpResponseHandler;

public class OperationResponseHandler extends AsyncHttpResponseHandler {

	private Object[] args;

	public OperationResponseHandler(Looper looper, Object... args) {
		super(looper);
		this.args = args;
	}

	public OperationResponseHandler(Object... args) {
		this.args = args;
	}

	@Override
	public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
		onFailure(arg0, arg3.getMessage(), args);
	}

	public void onFailure(int code, String errorMessage, Object[] args) {
	}

	@Override
	public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
		try {
			onSuccess(arg0, new ByteArrayInputStream(arg2), args);
		} catch (Exception e) {
			e.printStackTrace();
			onFailure(arg0, e.getMessage(), args);
		}
	}

	public void onSuccess(int code, ByteArrayInputStream is, Object[] args)
			throws Exception {

	}
}

 

 

 

 

 

 

 

OSChinaApi.java

package net.oschina.app.api.remote;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URLEncoder;

import net.oschina.app.AppContext;
import net.oschina.app.AppException;
import net.oschina.app.api.ApiHttpClient;
import net.oschina.app.bean.EventApplyData;
import net.oschina.app.bean.NewsList;
import net.oschina.app.bean.Report;
import net.oschina.app.bean.Tweet;
import net.oschina.app.team.bean.Team;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TLog;

import org.kymjs.kjframe.utils.KJLoger;

import android.text.TextUtils;

import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

public class OSChinaApi {

    /**
     * 登陆
     * 
     * @param username
     * @param password
     * @param handler
     */
    public static void login(String username, String password,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("username", username);
        params.put("pwd", password);
        params.put("keep_login", 1);
        String loginurl = "action/api/login_validate";
        ApiHttpClient.post(loginurl, params, handler);
    }

    /**
     * 获取新闻列表
     * 
     * @param catalog
     *            类别 (1,2,3)
     * @param page
     *            第几页
     * @param handler
     */
    public static void getNewsList(int catalog, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        if (catalog == NewsList.CATALOG_WEEK) {
            params.put("show", "week");
        } else if (catalog == NewsList.CATALOG_MONTH) {
            params.put("show", "month");
        }
        ApiHttpClient.get("action/api/news_list", params, handler);
    }

    public static void getBlogList(String type, int pageIndex,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("type", type);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/blog_list", params, handler);
    }

    public static void getPostList(int catalog, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/post_list", params, handler);
    }

    public static void getPostListByTag(String tag, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("tag", tag);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/post_list", params, handler);
    }

    public static void getTweetList(int uid, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/tweet_list", params, handler);
    }

    public static void getTweetTopicList(int page, String topic,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("pageIndex", page);
        params.put("title", topic);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/tweet_topic_list", params, handler);
    }

    public static void getTweetLikeList(AsyncHttpResponseHandler handler) {
        ApiHttpClient.get("action/api/my_tweet_like_list", handler);
    }

    public static void pubLikeTweet(int tweetId, int authorId,
            AsyncHttpResponseHandler handler) {

        RequestParams params = new RequestParams();
        params.put("tweetid", tweetId);
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("ownerOfTweet", authorId);
        ApiHttpClient.post("action/api/tweet_like", params, handler);
    }

    public static void pubUnLikeTweet(int tweetId, int authorId,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("tweetid", tweetId);
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("ownerOfTweet", authorId);
        ApiHttpClient.post("action/api/tweet_unlike", params, handler);
    }

    public static void getTweetLikeList(int tweetId, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("tweetid", tweetId);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/tweet_like_list", params, handler);

    }

    public static void getActiveList(int uid, int catalog, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("catalog", catalog);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/active_list", params, handler);
    }

    public static void getFriendList(int uid, int relation, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("relation", relation);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/friends_list", params, handler);
    }

    /**
     * 获取用户收藏
     * 
     * @param uid
     *            指定用户UID
     * @param type
     *            收藏类型: 0:全部收藏 1:软件 2:话题 3:博客 4:新闻 5:代码
     * @param page
     * @param handler
     */
    public static void getFavoriteList(int uid, int type, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("type", type);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/favorite_list", params, handler);
    }

    /**
     * 分类列表
     * 
     * @param tag
     *            第一级:0
     * @param handler
     */
    public static void getSoftwareCatalogList(int tag,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("tag", tag);
        ApiHttpClient.get("action/api/softwarecatalog_list", params, handler);
    }

    public static void getSoftwareTagList(int searchTag, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("searchTag", searchTag);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/softwaretag_list", params, handler);
    }

    /**
     * @param searchTag
     *              软件分类  推荐:recommend 最新:time 热门:view 国产:list_cn
     * @param page
     * @param handler
     */
    public static void getSoftwareList(String searchTag, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("searchTag", searchTag);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/software_list", params, handler);
    }

    /**
     * 获取评论列表
     * 
     * @param id
     * @param catalog
     *            1新闻 2帖子 3动弹 4动态
     * @param page
     * @param handler
     */
    public static void getCommentList(int id, int catalog, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("id", id);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/comment_list", params, handler);
    }

    public static void getBlogCommentList(int id, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("id", id);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/blogcomment_list", params, handler);
    }

    public static void getUserInformation(int uid, int hisuid, String hisname,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("hisuid", hisuid);
        params.put("hisname", hisname);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/user_information", params, handler);
    }

    @SuppressWarnings("deprecation")
    public static void getUserBlogList(int authoruid, final String authorname,
            final int uid, final int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("authoruid", authoruid);
        params.put("authorname", URLEncoder.encode(authorname));
        params.put("uid", uid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/userblog_list", params, handler);
    }

    public static void updateRelation(int uid, int hisuid, int newrelation,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("hisuid", hisuid);
        params.put("newrelation", newrelation);
        ApiHttpClient.post("action/api/user_updaterelation", params, handler);
    }

    public static void getMyInformation(int uid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        ApiHttpClient.get("action/api/my_information", params, handler);
    }

    /**
     * 获取新闻明细
     * 
     * @param newsId
     * @param handler
     */
    public static void getNewsDetail(int id, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("id", id);
        ApiHttpClient.get("action/api/news_detail", params, handler);
    }

    public static void getBlogDetail(int id, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("id", id);
        ApiHttpClient.get("action/api/blog_detail", params, handler);
    }

    /**
     * 获取软件详情
     * 
     * @param ident
     * @param handler
     */
    public static void getSoftwareDetail(String ident,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("ident",
                ident.replace(" ", ""));
        ApiHttpClient.get("action/api/software_detail", params, handler);
    }

    public static void getPostDetail(int id, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("id", id);
        ApiHttpClient.get("action/api/post_detail", params, handler);
    }

    public static void getTweetDetail(int id, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams("id", id);
        ApiHttpClient.get("action/api/tweet_detail", params, handler);
    }

    /**
     * 用户针对某个新闻,帖子,动弹,消息发表评论的接口,参数使用POST方式提交
     * 
     * @param catalog
     *               1新闻  2 帖子  3 动弹  4消息中心
     * @param id
     *            被评论的某条新闻,帖子,动弹或者某条消息的id
     * @param uid
     *            当天登陆用户的UID
     * @param content
     *            发表的评论内容
     * @param isPostToMyZone
     *            是否转发到我的空间,0不转发  1转发到我的空间(注意该功能之对某条动弹进行评论是有效,其他情况下服务器借口可以忽略该参数)
     * @param handler
     */
    public static void publicComment(int catalog, int id, int uid,
            String content, int isPostToMyZone, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("id", id);
        params.put("uid", uid);
        params.put("content", content);
        params.put("isPostToMyZone", isPostToMyZone);
        ApiHttpClient.post("action/api/comment_pub", params, handler);
    }

    public static void replyComment(int id, int catalog, int replyid,
            int authorid, int uid, String content,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("id", id);
        params.put("uid", uid);
        params.put("content", content);
        params.put("replyid", replyid);
        params.put("authorid", authorid);
        ApiHttpClient.post("action/api/comment_reply", params, handler);
    }

    public static void publicBlogComment(int blog, int uid, String content,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("blog", blog);
        params.put("uid", uid);
        params.put("content", content);
        ApiHttpClient.post("action/api/blogcomment_pub", params, handler);
    }

    public static void replyBlogComment(int blog, int uid, String content,
            int reply_id, int objuid, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("blog", blog);
        params.put("uid", uid);
        params.put("content", content);
        params.put("reply_id", reply_id);
        params.put("objuid", objuid);
        ApiHttpClient.post("action/api/blogcomment_pub", params, handler);
    }

    public static void pubTweet(Tweet tweet, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", tweet.getAuthorid());
        params.put("msg", tweet.getBody());

        // Map<String, File> files = new HashMap<String, File>();
        if (!TextUtils.isEmpty(tweet.getImageFilePath())) {
            try {
                params.put("img", new File(tweet.getImageFilePath()));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        if (!TextUtils.isEmpty(tweet.getAudioPath())) {
            try {
                params.put("amr", new File(tweet.getAudioPath()));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        ApiHttpClient.post("action/api/tweet_pub", params, handler);
    }

    public static void pubSoftWareTweet(Tweet tweet, int softid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", tweet.getAuthorid());
        params.put("msg", tweet.getBody());
        params.put("project", softid);
        ApiHttpClient.post("action/api/software_tweet_pub", params, handler);
    }

    public static void deleteTweet(int uid, int tweetid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("tweetid", tweetid);
        ApiHttpClient.post("action/api/tweet_delete", params, handler);
    }

    public static void deleteComment(int id, int catalog, int replyid,
            int authorid, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("id", id);
        params.put("catalog", catalog);
        params.put("replyid", replyid);
        params.put("authorid", authorid);
        ApiHttpClient.post("action/api/comment_delete", params, handler);
    }

    public static void deleteBlog(int uid, int authoruid, int id,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("authoruid", authoruid);
        params.put("id", id);
        ApiHttpClient.post("action/api/userblog_delete", params, handler);
    }

    public static void deleteBlogComment(int uid, int blogid, int replyid,
            int authorid, int owneruid, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("blogid", blogid);
        params.put("replyid", replyid);
        params.put("authorid", authorid);
        params.put("owneruid", owneruid);
        ApiHttpClient.post("action/api/blogcomment_delete", params, handler);
    }

    /**
     * 用户添加收藏
     * 
     * @param uid
     *            用户UID
     * @param objid
     *            比如是新闻ID 或者问答ID 或者动弹ID
     * @param type
     *            1:软件 2:话题 3:博客 4:新闻 5:代码
     */
    public static void addFavorite(int uid, int objid, int type,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("objid", objid);
        params.put("type", type);
        ApiHttpClient.post("action/api/favorite_add", params, handler);
    }

    public static void delFavorite(int uid, int objid, int type,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("objid", objid);
        params.put("type", type);
        ApiHttpClient.post("action/api/favorite_delete", params, handler);
    }

    public static void getSearchList(String catalog, String content,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("catalog", catalog);
        params.put("content", content);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/search_list", params, handler);
    }

    public static void publicMessage(int uid, int receiver, String content,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("receiver", receiver);
        params.put("content", content);
        ApiHttpClient.post("action/api/message_pub", params, handler);
    }

    public static void deleteMessage(int uid, int friendid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("friendid", friendid);
        ApiHttpClient.post("action/api/message_delete", params, handler);
    }

    public static void forwardMessage(int uid, String receiverName,
            String content, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("receiverName", receiverName);
        params.put("content", content);
        ApiHttpClient.post("action/api/message_pub", params, handler);
    }

    public static void getMessageList(int uid, int pageIndex,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/message_list", params, handler);
    }

    public static void updatePortrait(int uid, File portrait,
            AsyncHttpResponseHandler handler) throws FileNotFoundException {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("portrait", portrait);
        ApiHttpClient.post("action/api/portrait_update", params, handler);
    }

    public static void getNotices(AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        ApiHttpClient.get("action/api/user_notice", params, handler);
    }

    /**
     * 清空通知消息
     * 
     * @param uid
     * @param type
     *            1:@我的信息 2:未读消息 3:评论个数 4:新粉丝个数
     * @return
     * @throws AppException
     */
    public static void clearNotice(int uid, int type,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("type", type);
        ApiHttpClient.post("action/api/notice_clear", params, handler);
    }

    public static void singnIn(String url, AsyncHttpResponseHandler handler) {
        ApiHttpClient.getDirect(url, handler);
    }

    /**
     * 获取软件的动态列表
     * 
     * @param softid
     * @param handler
     */
    public static void getSoftTweetList(int softid, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("project", softid);
        params.put("pageIndex", page);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/software_tweet_list", params, handler);
    }

    public static void checkUpdate(AsyncHttpResponseHandler handler) {
        ApiHttpClient.get("MobileAppVersion.xml", handler);
    }

    /**
     * 查找用户
     * 
     * @param username
     * @param handler
     */
    public static void findUser(String username,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("name", username);
        ApiHttpClient.get("action/api/find_user", params, handler);
    }

    /**
     * 获取活动列表
     * 
     * @param pageIndex
     * @param uid
     *            <= 0 近期活动 实际的用户ID 则获取用户参与的活动列表,需要已登陆的用户
     * @param handler
     */
    public static void getEventList(int pageIndex, int uid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("pageIndex", pageIndex);
        params.put("uid", uid);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/event_list", params, handler);
    }

    /**
     * 获取某活动已出席的人员列表
     * 
     * @param eventId
     * @param pageIndex
     * @param handler
     */
    public static void getEventApplies(int eventId, int pageIndex,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("pageIndex", pageIndex);
        params.put("event_id", eventId);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/event_attend_user", params, handler);
    }

    /**
     * 举报
     * 
     * @param report
     * @param handler
     */
    public static void report(Report report, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("obj_id", report.getReportId());
        params.put("url", report.getLinkAddress());
        params.put("obj_type", report.getReason());
        if (report.getOtherReason() != null
                && !StringUtils.isEmpty(report.getOtherReason())) {
            params.put("memo", report.getOtherReason());
        } else {
            params.put("memo", "其他原因");
        }
        TLog.log("Test", report.getReportId() + "" + report.getLinkAddress()
                + report.getReason() + report.getOtherReason());
        ApiHttpClient.post("action/communityManage/report", params, handler);
    }

    /**
     * 摇一摇,随机数据
     * 
     * @param handler
     */
    public static void shake(AsyncHttpResponseHandler handler) {
        shake(-1, handler);
    }

    /**
     * 摇一摇指定请求类型
     */
    public static void shake(int type, AsyncHttpResponseHandler handler) {
        String inter = "action/api/rock_rock";
        if (type > 0) {
            inter = (inter + "/?type=" + type);
        }
        ApiHttpClient.get(inter, handler);
    }

    /**
     * 活动报名
     * 
     * @param data
     * @param handler
     */
    public static void eventApply(EventApplyData data,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("event", data.getEvent());
        params.put("user", data.getUser());
        params.put("name", data.getName());
        params.put("gender", data.getGender());
        params.put("mobile", data.getPhone());
        params.put("company", data.getCompany());
        params.put("job", data.getJob());
        ApiHttpClient.post("action/api/event_apply", params, handler);
    }

    private static void uploadLog(String data, String report,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("app", "1");
        params.put("report", report);
        params.put("msg", data);
        ApiHttpClient.post("action/api/user_report_to_admin", params, handler);
    }

    /**
     * BUG上报
     * 
     * @param data
     * @param handler
     */
    public static void uploadLog(String data, AsyncHttpResponseHandler handler) {
        uploadLog(data, "1", handler);
    }

    /**
     * 反馈意见
     * 
     * @param data
     * @param handler
     */
    public static void feedback(String data, AsyncHttpResponseHandler handler) {
        uploadLog(data, "2", handler);
    }

    /**
     * team动态
     * 
     * @param team
     * @param page
     * @param handler
     */
    public static void teamDynamic(Team team, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        // int uid = AppContext.getInstance().getLoginUid();
        // params.put("uid", uid);
        params.put("teamid", team.getId());
        params.put("pageIndex", page);
        params.put("pageSize", 20);
        params.put("type", "all");
        ApiHttpClient.get("action/api/team_active_list", params, handler);
    }

    /**
     * 获取team列表
     * 
     * @param handler
     */
    public static void teamList(AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        ApiHttpClient.get("action/api/team_list", params, handler);
    }

    /**
     * 获取team成员列表
     * 
     * @param handler
     */
    public static void getTeamMemberList(int teamid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        ApiHttpClient.get("action/api/team_member_list", params, handler);
    }

    /**
     * 获取team成员个人信息
     * 
     * @param handler
     */
    public static void getTeamUserInfo(String teamid, String uid,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("uid", uid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", 20);
        ApiHttpClient.get("action/api/team_user_information", params, handler);
    }

    /**
     * 获取我的任务中进行中、未完成、已完成等状态的数量
     */
    public static void getMyIssueState(String teamid, String uid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("uid", uid);
        ApiHttpClient.get("action/api/team_user_issue_information", params,
                handler);
    }

    /**
     * 获取指定用户的动态
     */
    public static void getUserDynamic(int teamid, String uid, int pageIndex,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", 20);
        params.put("type", "git");
        params.put("uid", uid);
        ApiHttpClient.get("action/api/team_active_list", params, handler);
    }

    /**
     * 动态详情
     * 
     * @param activeid
     * @param teamid
     * @param uid
     * @param handler
     */
    public static void getDynamicDetail(int activeid, int teamid, int uid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("uid", uid);
        params.put("activeid", activeid);
        ApiHttpClient.get("action/api/team_active_detail", params, handler);
    }

    /**
     * 获取指定用户的任务
     */
    public static void getMyIssue(String teamid, String uid, int pageIndex,
            String type, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("uid", uid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", 20);
        params.put("state", type);
        params.put("projectid", "-1");
        ApiHttpClient.get("action/api/team_issue_list", params, handler);
    }

    /**
     * 获取指定周周报
     * 
     * @param teamid
     * @param year
     * @param week
     * @param handler
     */
    public static void getDiaryFromWhichWeek(int teamid, int year, int week,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("year", year);
        params.put("week", week);
        ApiHttpClient.get("action/api/team_diary_list", params, handler);
    }

    /**
     * 删除一个便签
     * 
     * @param id
     *            便签id
     * @param uid
     *            用户id
     */
    public static void deleteNoteBook(int id, int uid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("id", id); // 便签id
        ApiHttpClient
                .get("action/api/team_stickynote_recycle", params, handler);
    }

    public static void getNoteBook(int uid, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        ApiHttpClient.get("action/api/team_sticky_list", params, handler);
    }

    /**
     * 获取指定周报的详细信息
     * 
     * @param teamid
     * @param diaryid
     * @param handler
     */
    public static void getDiaryDetail(int teamid, int diaryid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("diaryid", diaryid);
        ApiHttpClient.get("action/api/team_diary_detail", params, handler);
    }

    /**
     * diary评论列表
     * 
     * @param teamid
     * @param diaryid
     * @param handler
     */
    public static void getDiaryComment(int teamid, int diaryid,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamid);
        params.put("id", diaryid);
        params.put("type", "diary");
        params.put("pageIndex", 0);
        params.put("pageSize", "20");
        KJLoger.debug(teamid + "==getDiaryComment接口=" + diaryid);
        ApiHttpClient
                .get("action/api/team_reply_list_by_type", params, handler);
    }

    /**
     * 周报评论(以后可改为全局评论)
     * 
     * @param uid
     * @param teamid
     * @param diaryId
     * @param content
     * @param handler
     */
    public static void sendComment(int uid, int teamid, int diaryId,
            String content, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("teamid", teamid);
        params.put("type", "118");
        params.put("tweetid", diaryId);
        params.put("content", content);
        ApiHttpClient.post("action/api/team_tweet_reply", params, handler);
    }

    /***
     * 客户端扫描二维码登陆
     * 
     * @author 火蚁 2015-3-13 上午11:45:47
     * 
     * @return void
     * @param url
     * @param handler
     */
    public static void scanQrCodeLogin(String url,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        String uuid = url.substring(url.lastIndexOf("=") + 1);
        params.put("uuid", uuid);
        ApiHttpClient.getDirect(url, handler);
    }
}

 

 

 

 

 

OSChinaTeamApi.java

package net.oschina.app.api.remote;

import java.io.File;
import java.io.FileNotFoundException;

import net.oschina.app.AppContext;
import net.oschina.app.api.ApiHttpClient;
import net.oschina.app.team.bean.TeamIssue;
import net.oschina.app.team.bean.TeamProject;
import android.text.TextUtils;

import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

/**
 * osc team api集合类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2015年1月14日 下午3:32:18
 * 
 */
public class OSChinaTeamApi {

    /**
     * 获取团队项目列表
     * 
     * @param teamId
     * @param handler
     */
    public static void getTeamProjectList(int teamId,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        ApiHttpClient.get("action/api/team_project_list", params, handler);
    }

    /**
     * 获取team动态列表
     * 
     * @param teamId
     * @param activeId
     * @param pageIndex
     * @param handler
     */
    public static void getTeamCommentList(int teamId, int activeId,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("id", activeId);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", 20);
        ApiHttpClient.get("action/api/team_reply_list_by_activeid", params,
                handler);
    }

    /***
     * 获取团队绑定项目的成员列表(包括管理员以及开发者)
     * 
     * @author 火蚁 2015-2-5 下午6:45:41
     * 
     * @return void
     * @param teamId
     * @param teamProject
     * @param handler
     */
    public static void getTeamProjectMemberList(int teamId,
            TeamProject teamProject, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("projectid", teamProject.getGit().getId());
        String source = teamProject.getSource();
        if (source != null && !TextUtils.isEmpty(source)) {

            params.put("source", teamProject.getSource());
        }
        ApiHttpClient.get("action/api/team_project_member_list", params,
                handler);
    }

    /***
     * 获取项目的动态列表
     * 
     * @author 火蚁 2015-3-2 下午5:18:54
     * 
     * @return void
     * @param teamId
     * @param project
     * @param type
     *            "all"(default),"issue","code","other"
     * @param page
     * @param handler
     */
    public static void getTeamProjectActiveList(int teamId,
            TeamProject project, String type, int page,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("projectid", project.getGit().getId());
        if (!TextUtils.isEmpty(project.getSource())) {
            params.put("source", project.getSource());
        }
        params.put("type", type);
        params.put("pageIndex", page);
        ApiHttpClient.get("action/api/team_project_active_list", params,
                handler);
    }

    /**
     * 获取某项目的任务列表
     * 
     * @param uId
     *            用户id
     * @param teamId
     *            团队id
     * @param projectId
     *            项目id(当<=0或不设置时,查询非项目的任务列表)
     * @param source
     *            "Git@OSC","GitHub"(只有设置了projectid值,这里才需要设置该值)
     */
    public static void getTeamCatalogIssueList(int uId, int teamId,
            int projectId, String source, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uId);
        params.put("teamid", teamId);
        params.put("projectid", projectId);
        params.put("source", source);
        ApiHttpClient.get("action/api/team_project_catalog_list", params,
                handler);
    }

    /**
     * 获取指定任务列表的任务列表
     * 
     * @param teamId
     * @param projectId
     *            项目id(-1获取非项目任务列表, 0获取所有任务列表)
     * @param catalogId
     *            任务列表的的目录id
     * @param source
     *            "Team@OSC"(default),"Git@OSC","GitHub",如果指定了projectid的值,
     *            这个值就是必须的
     * @param uid
     *            如果指定该值,则获取该id用户相关的任务
     * @param state
     *            "all"(default),"opened","closed","outdate"
     * @param scope
     *            "tome"(default,指派给我的任务),"meto"(我指派的任务)
     * @param pageIndex
     * @param pageSize
     * @param handler
     */
    public static void getTeamIssueList(int teamId, int projectId,
            int catalogId, String source, int uid, String state, String scope,
            int pageIndex, int pageSize, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("projectid", projectId);
        params.put("catalogid", catalogId);
        params.put("source", source);
        params.put("uid", uid);
        params.put("state", state);
        params.put("scope", scope);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", pageSize);
        ApiHttpClient.get("action/api/team_issue_list", params, handler);
    }

    /***
     * 改变一个任务的状态
     * 
     * @author 火蚁 2015-3-6 上午11:44:01
     * 
     * @return void
     * @param teamId
     * @param issue
     * @param target
     *            修改的属性("state" : 状态, "assignee" 指派人, "deadline" : 截止日期)
     * @param handler
     */
    public static void changeIssueState(int teamId, TeamIssue issue,
            String target, AsyncHttpResponseHandler handler) {
        if (issue == null)
            return;
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("teamid", teamId);
        params.put("target", target);
        params.put("issueid", issue.getId());
        if (target.equals("state")) {
            params.put("state", issue.getState());
        } else if (target.equals("assignee")) {
            params.put("assignee", issue.getToUser().getId());
        } else if (target.equals("deadline")) {
            params.put("deadline", issue.getDeadlineTime());
        }
        ApiHttpClient.post("action/api/team_issue_update", params, handler);
    }

    public static void pubTeamNewIssue(RequestParams params,
            AsyncHttpResponseHandler handler) {
        ApiHttpClient.post("action/api/team_issue_pub", params, handler);
    }

    /***
     * 获取团队的讨论区列表
     * 
     * @param type
     * @param teamId
     * @param uid
     * @param pageIndex
     * @param handler
     */
    public static void getTeamDiscussList(String type, int teamId, int uid,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("type", type);
        params.put("teamid", teamId);
        params.put("uid", uid);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/team_discuss_list", params, handler);
    }

    /***
     * 获取讨论贴详情
     * 
     * @author 火蚁 2015-2-2 下午6:19:54
     * 
     * @return void
     * @param teamId
     * @param discussId
     * @param handler
     */
    public static void getTeamDiscussDetail(int teamId, int discussId,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("discussid", discussId);
        ApiHttpClient.get("action/api/team_discuss_detail", params, handler);
    }

    /***
     * 发表讨论贴评论
     * 
     * @author 火蚁 2015-2-3 下午2:42:54
     * 
     * @return void
     * @param uid
     * @param teamId
     * @param dicussId
     * @param content
     * @param handler
     */
    public static void pubTeamDiscussReply(int uid, int teamId, int discussId,
            String content, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("teamid", teamId);
        params.put("discussid", discussId);
        params.put("content", content);
        ApiHttpClient.post("action/api/team_discuss_reply", params, handler);
    }

    /***
     * 发表一条综合评论 动态、分享内容、周报
     * 
     * @author 火蚁 2015-3-6 下午3:31:07
     * 
     * @return void
     * @param teamId
     * @param type
     *            普通动态-110,分享内容-114, 周报-118
     * @param tweetId
     * @param content
     * @param handler
     */
    public static void pubTeamTweetReply(int teamId, int type, long tweetId,
            String content, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("type", type);
        params.put("teamid", teamId);
        params.put("tweetid", tweetId);
        params.put("content", content);
        ApiHttpClient.post("action/api/team_tweet_reply", params, handler);
    }

    /***
     * 获取团队任务详情
     * 
     * @author 火蚁 2015-1-27 下午7:47:17
     * 
     */
    public static void getTeamIssueDetail(int teamId, int issueId,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("issueid", issueId);
        ApiHttpClient.get("action/api/team_issue_detail", params, handler);
    }

    /***
     * 获取团队的周报列表
     * 
     * @param uid
     * @param teamId
     * @param year
     * @param week
     * @param pageIndex
     * @param handler
     */
    public static void getTeamDiaryList(int uid, int teamId, int year,
            int week, int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", uid);
        params.put("teamid", teamId);
        params.put("year", year);
        params.put("week", week);
        params.put("pageIndex", pageIndex);
        params.put("pageSize", AppContext.PAGE_SIZE);
        ApiHttpClient.get("action/api/team_diary_list", params, handler);
    }

    /***
     * 任务、周报、讨论的回复列表
     * 
     * @author 火蚁 2015-2-2 上午11:39:04
     * 
     * @return void
     * @param teamId
     * @param id
     * @param type
     *            评论列表的类型(周报diary,讨论discuss,任务issue)
     * @param pageIndex
     * @param handler
     */
    public static void getTeamReplyList(int teamId, int id, String type,
            int pageIndex, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("id", id);
        params.put("type", type);
        params.put("pageIndex", pageIndex);
        ApiHttpClient
                .get("action/api/team_reply_list_by_type", params, handler);

    }

    /***
     * 发表一个新的团队动态
     * 
     * @author 火蚁 2015-3-9 下午2:46:13
     * 
     * @return void
     * @param teamId
     * @param content
     * @param img
     * @param handler
     */
    public static void pubTeamNewActive(int teamId, String content, File img,
            AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("teamid", teamId);
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("msg", content);
        params.put("appid", 3);
        if (img != null) {

            try {
                params.put("img", img);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        ApiHttpClient.post("action/api/team_tweet_pub", params, handler);
    }

    /***
     * 更新子任务属性
     * 
     * @author 火蚁 2015-3-10 下午4:53:49
     * 
     * @return void
     * @param teamId
     * @param target
     * @param childIssue
     * @param handler
     */
    public static void updateChildIssue(int teamId, String target,
            TeamIssue childIssue, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("teamid", teamId);
        params.put("childissueid", childIssue.getId());
        params.put("target", target);
        if (target.equals("state")) {
            params.put("state", childIssue.getState());
        } else {
            params.put("title", childIssue.getTitle());
        }
        ApiHttpClient.post("action/api/team_issue_update_child_issue", params,
                handler);
    }

    /***
     * 发表任务评论
     * 
     * @author 火蚁 2015-3-13 下午6:22:41
     * 
     * @return void
     * @param teamId
     * @param issueId
     * @param content
     * @param handler
     */
    public static void pubTeamIssueReply(int teamId, int issueId,
            String content, AsyncHttpResponseHandler handler) {
        RequestParams params = new RequestParams();
        params.put("uid", AppContext.getInstance().getLoginUid());
        params.put("teamid", teamId);
        params.put("content", content);
        params.put("issueid", issueId);
        ApiHttpClient.post("action/api/team_issue_reply", params, handler);
    }
}

 

 

 

 

 

 

Base.java

package net.oschina.app.bean;

import java.io.Serializable;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 实体基类:实现序列化
 * @author liux (http://my.oschina.net/liux)
 * @version 1.0
 * @created 2012-3-21
 */
@SuppressWarnings("serial")
public abstract class Base implements Serializable {

	@XStreamAlias("notice")
	protected Notice notice;

	public Notice getNotice() {
		return notice;
	}

	public void setNotice(Notice notice) {
		this.notice = notice;
	}
}

 

 

 

 

 

ListEntity.java

package net.oschina.app.bean;

import java.io.Serializable;
import java.util.List;

public interface ListEntity<T extends Entity> extends Serializable {

    public List<T> getList();
}

 

 

 

 

 

 

 

Entity.java

package net.oschina.app.bean;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 实体类
 * 
 * @author liux (http://my.oschina.net/liux)
 * @version 1.0
 * @created 2012-3-21
 */
@SuppressWarnings("serial")
public abstract class Entity extends Base {

    @XStreamAlias("id")
    protected int id;

    protected String cacheKey;

    public int getId() {
	return id;
    }

    public void setId(int id) {
	this.id = id;
    }

    public String getCacheKey() {
	return cacheKey;
    }

    public void setCacheKey(String cacheKey) {
	this.cacheKey = cacheKey;
    }
}

 

 

 

 

 

 

Active.java

package net.oschina.app.bean;

import java.io.Serializable;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 动态实体类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年10月22日 下午3:22:09
 * 
 */
@SuppressWarnings("serial")
@XStreamAlias("active")
public class Active extends Entity {

	public final static int CATALOG_OTHER = 0;// 其他
	public final static int CATALOG_NEWS = 1;// 新闻
	public final static int CATALOG_POST = 2;// 帖子
	public final static int CATALOG_TWEET = 3;// 动弹
	public final static int CATALOG_BLOG = 4;// 博客

	public final static int CLIENT_MOBILE = 2;
	public final static int CLIENT_ANDROID = 3;
	public final static int CLIENT_IPHONE = 4;
	public final static int CLIENT_WINDOWS_PHONE = 5;
	
	@XStreamAlias("portrait")
	private String portrait;

	@XStreamAlias("message")
	private String message;

	@XStreamAlias("author")
	private String author;

	@XStreamAlias("authorid")
	private int authorId;

	@XStreamAlias("activetype")
	private int activeType;

	@XStreamAlias("objectID")
	private int objectId;

	@XStreamAlias("catalog")
	private int catalog;

	@XStreamAlias("objecttype")
	private int objectType;

	@XStreamAlias("objectcatalog")
	private int objectCatalog;

	@XStreamAlias("objecttitle")
	private String objectTitle;

	@XStreamAlias("objectreply")
	private ObjectReply objectReply;

	@XStreamAlias("commentCount")
	private int commentCount;

	@XStreamAlias("pubDate")
	private String pubDate;

	@XStreamAlias("tweetimage")
	private String tweetimage;
	
	@XStreamAlias("tweetattach")
	private String tweetattach;

	@XStreamAlias("appclient")
	private int appClient;

	@XStreamAlias("url")
	private String url;

	public String getPortrait() {
		return portrait;
	}

	public void setPortrait(String portrait) {
		this.portrait = portrait;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public int getAuthorId() {
		return authorId;
	}

	public void setAuthorId(int authorId) {
		this.authorId = authorId;
	}

	public int getActiveType() {
		return activeType;
	}

	public void setActiveType(int activeType) {
		this.activeType = activeType;
	}

	public int getObjectId() {
		return objectId;
	}

	public void setObjectId(int objectId) {
		this.objectId = objectId;
	}

	public int getCatalog() {
		return catalog;
	}

	public void setCatalog(int catalog) {
		this.catalog = catalog;
	}

	public int getObjectType() {
		return objectType;
	}

	public void setObjectType(int objectType) {
		this.objectType = objectType;
	}

	public int getObjectCatalog() {
		return objectCatalog;
	}

	public void setObjectCatalog(int objectCatalog) {
		this.objectCatalog = objectCatalog;
	}

	public String getObjectTitle() {
		return objectTitle;
	}

	public void setObjectTitle(String objectTitle) {
		this.objectTitle = objectTitle;
	}

	public ObjectReply getObjectReply() {
		return objectReply;
	}

	public void setObjectReply(ObjectReply objectReply) {
		this.objectReply = objectReply;
	}

	public int getCommentCount() {
		return commentCount;
	}

	public void setCommentCount(int commentCount) {
		this.commentCount = commentCount;
	}

	public String getPubDate() {
		return pubDate;
	}

	public void setPubDate(String pubDate) {
		this.pubDate = pubDate;
	}

	public String getTweetattach() {
		return tweetattach;
	}

	public void setTweetattach(String tweetattach) {
		this.tweetattach = tweetattach;
	}

	public String getTweetimage() {
		return tweetimage;
	}

	public void setTweetimage(String tweetimage) {
		this.tweetimage = tweetimage;
	}

	public int getAppClient() {
		return appClient;
	}

	public void setAppClient(int appClient) {
		this.appClient = appClient;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	@XStreamAlias("objectreply")
	public static class ObjectReply implements Serializable {
		@XStreamAlias("objectname")
		public String objectName;

		@XStreamAlias("objectbody")
		public String objectBody;

		public String getObjectName() {
			return objectName;
		}

		public void setObjectName(String objectName) {
			this.objectName = objectName;
		}

		public String getObjectBody() {
			return objectBody;
		}

		public void setObjectBody(String objectBody) {
			this.objectBody = objectBody;
		}
	}
}

 

 

 

 

 

ActiveList.java

package net.oschina.app.bean;

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 动态实体列表
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年10月22日 下午3:34:21
 * 
 */
@SuppressWarnings("serial")
@XStreamAlias("oschina")
public class ActiveList extends Entity implements ListEntity<Active> {

    public final static int CATALOG_LASTEST = 1;// 最新
    public final static int CATALOG_ATME = 2;// @我
    public final static int CATALOG_COMMENT = 3;// 评论
    public final static int CATALOG_MYSELF = 4;// 我自己

    @XStreamAlias("pagesize")
    private int pageSize;

    @XStreamAlias("activeCount")
    private int activeCount;

    @XStreamAlias("activies")
    private List<Active> activelist = new ArrayList<Active>();
    
    @XStreamAlias("result")
    private Result result;

    public int getPageSize() {
	return pageSize;
    }

    public int getActiveCount() {
	return activeCount;
    }

    public List<Active> getActivelist() {
	return activelist;
    }

    @Override
    public List<Active> getList() {
	return activelist;
    }

    public Result getResult() {
        return result;
    }

    public void setResult(Result result) {
        this.result = result;
    }
}

 

 

 

 

 

 

Constants.java

package net.oschina.app.bean;

/**
 * 常量类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年10月27日 下午12:14:42
 * 
 */

public class Constants {

    public static final String INTENT_ACTION_USER_CHANGE = "net.oschina.action.USER_CHANGE";

    public static final String INTENT_ACTION_COMMENT_CHANGED = "net.oschina.action.COMMENT_CHANGED";

    public static final String INTENT_ACTION_NOTICE = "net.oschina.action.APPWIDGET_UPDATE";

    public static final String INTENT_ACTION_LOGOUT = "net.oschina.action.LOGOUT";

    public static final String WEICHAT_APPID = "wx41be5fe48092e94c";
    public static final String WEICHAT_SECRET = "0101b0595ffe2042c214420fac358abc";

    public static final String QQ_APPID = "100942993";
    public static final String QQ_APPKEY = "8edd3cc7ca8dcc15082d6fe75969601b";
}

 

 

 

 

 

AlarmReceiver.java

package net.oschina.app.broadcast;

import net.oschina.app.service.NoticeUtils;
import net.oschina.app.util.TLog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AlarmReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		TLog.log("onReceive ->net.oschina.app收到定时获取消息");
		NoticeUtils.requestNotice(context);
	}
}

 

 

 

 

 

 

 

CacheManager.java

package net.oschina.app.cache;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import net.oschina.app.util.TDevice;
import android.content.Context;

public class CacheManager {

    // wifi缓存时间为5分钟
    private static long wifi_cache_time = 5 * 60 * 1000;
    // 其他网络环境为1小时
    private static long other_cache_time = 60 * 60 * 1000;

    /**
     * 保存对象
     * 
     * @param ser
     * @param file
     * @throws IOException
     */
    public static boolean saveObject(Context context, Serializable ser,
	    String file) {
	FileOutputStream fos = null;
	ObjectOutputStream oos = null;
	try {
	    fos = context.openFileOutput(file, Context.MODE_PRIVATE);
	    oos = new ObjectOutputStream(fos);
	    oos.writeObject(ser);
	    oos.flush();
	    return true;
	} catch (Exception e) {
	    e.printStackTrace();
	    return false;
	} finally {
	    try {
		oos.close();
	    } catch (Exception e) {
	    }
	    try {
		fos.close();
	    } catch (Exception e) {
	    }
	}
    }

    /**
     * 读取对象
     * 
     * @param file
     * @return
     * @throws IOException
     */
    public static Serializable readObject(Context context, String file) {
	if (!isExistDataCache(context, file))
	    return null;
	FileInputStream fis = null;
	ObjectInputStream ois = null;
	try {
	    fis = context.openFileInput(file);
	    ois = new ObjectInputStream(fis);
	    return (Serializable) ois.readObject();
	} catch (FileNotFoundException e) {
	} catch (Exception e) {
	    e.printStackTrace();
	    // 反序列化失败 - 删除缓存文件
	    if (e instanceof InvalidClassException) {
		File data = context.getFileStreamPath(file);
		data.delete();
	    }
	} finally {
	    try {
		ois.close();
	    } catch (Exception e) {
	    }
	    try {
		fis.close();
	    } catch (Exception e) {
	    }
	}
	return null;
    }

    /**
     * 判断缓存是否存在
     * 
     * @param cachefile
     * @return
     */
    public static boolean isExistDataCache(Context context, String cachefile) {
	if (context == null)
	    return false;
	boolean exist = false;
	File data = context.getFileStreamPath(cachefile);
	if (data.exists())
	    exist = true;
	return exist;
    }

    /**
     * 判断缓存是否已经失效
     */
    public static boolean isCacheDataFailure(Context context, String cachefile) {
	File data = context.getFileStreamPath(cachefile);
	if (!data.exists()) {

	    return false;
	}
	long existTime = System.currentTimeMillis() - data.lastModified();
	boolean failure = false;
	if (TDevice.getNetworkType() == TDevice.NETTYPE_WIFI) {
	    failure = existTime > wifi_cache_time ? true : false;
	} else {
	    failure = existTime > other_cache_time ? true : false;
	}
	return failure;
    }
}

 

 

 

 

 

 

DataCleanManager.java

package net.oschina.app.cache;

import java.io.File;

import android.content.Context;
import android.os.Environment;

/**
 * 数据删除工具类
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年10月27日 上午10:18:22
 * 
 */
public class DataCleanManager {
	
	/**
	 * 清除本应用内部缓存
	 * (/data/data/com.xxx.xxx/cache)
	 * @param context
	 */
	public static void cleanInternalCache(Context context) {
		deleteFilesByDirectory(context.getCacheDir());
		deleteFilesByDirectory(context.getFilesDir());
	}

	/**
	 * 清楚本应用所有数据库
	 * (/data/data/com.xxx.xxx/databases)
	 * @param context
	 */
	public static void cleanDatabases(Context context) {
		deleteFilesByDirectory(new File("/data/data/"
				+ context.getPackageName() + "/databases"));
	}

	/**
	 * 清除本应用SharedPreference
	 * (/data/data/com.xxx.xxx/shared_prefs)
	 * @param context
	 */
	public static void cleanSharedPreference(Context context) {
		deleteFilesByDirectory(new File("/data/data/"
				+ context.getPackageName() + "/shared_prefs"));
	}
	
	/**
	 * 按名字清除本应用数据库
	 * @param context
	 * @param dbName
	 */
	public static void cleanDatabaseByName(Context context, String dbName) {
		context.deleteDatabase(dbName);
	}

	/**
	 * 清除/data/data/com.xxx.xxx/files下的内容
	 * @param context
	 */
	public static void cleanFiles(Context context) {
		deleteFilesByDirectory(context.getFilesDir());
	}

	/**
	 * 清除外部cache下的内容(/mnt/sdcard/android/data/com.xxx.xxx/cache)
	 * @param context
	 */
	public static void cleanExternalCache(Context context) {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			deleteFilesByDirectory(context.getExternalCacheDir());
		}
	}

	/**
	 * 清除自定义路径下的文件,使用需小心,请不要误删。而且只支持目录下的文件删除
	 * @param filePath
	 */
	public static void cleanCustomCache(String filePath) {
		deleteFilesByDirectory(new File(filePath));
	}
	
	/**
	 * 清除自定义路径下的文件,使用需小心,请不要误删。而且只支持目录下的文件删除
	 * @param filePath
	 */
	public static void cleanCustomCache(File file) {
		deleteFilesByDirectory(file);
	}

	/**
	 * 清除本应用所有的数据
	 * @param context
	 * @param filepath
	 */
	public static void cleanApplicationData(Context context, String... filepath) {
		cleanInternalCache(context);
		cleanExternalCache(context);
		cleanDatabases(context);
		cleanSharedPreference(context);
		cleanFiles(context);
		for (String filePath : filepath) {
			cleanCustomCache(filePath);
		}
	}

	/**
	 * 删除方法 这里只会删除某个文件夹下的文件,如果传入的directory是个文件,将不做处理 
	 * @param directory
	 */
	private static void deleteFilesByDirectory(File directory) {
		if (directory != null && directory.exists() && directory.isDirectory()) {
			for (File child : directory.listFiles()) {
				if (child.isDirectory()) {
					deleteFilesByDirectory(child);
				} 
				child.delete();
			}
		}
	}
}

 

 

 

 

 

 

DiskLruCache.java

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.oschina.app.cache;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 ******************************************************************************
 * Taken from the JB source code, can be found in:
 * libcore/luni/src/main/java/libcore/io/DiskLruCache.java
 * or direct link:
 * https://android.googlesource.com/platform/libcore/+/android-4.1.1_r1/luni/src/main/java/libcore/io/DiskLruCache.java
 ******************************************************************************
 *
 * A cache that uses a bounded amount of space on a filesystem. Each cache
 * entry has a string key and a fixed number of values. Values are byte
 * sequences, accessible as streams or files. Each value must be between {@code
 * 0} and {@code Integer.MAX_VALUE} bytes in length.
 *
 * <p>The cache stores its data in a directory on the filesystem. This
 * directory must be exclusive to the cache; the cache may delete or overwrite
 * files from its directory. It is an error for multiple processes to use the
 * same cache directory at the same time.
 *
 * <p>This cache limits the number of bytes that it will store on the
 * filesystem. When the number of stored bytes exceeds the limit, the cache will
 * remove entries in the background until the limit is satisfied. The limit is
 * not strict: the cache may temporarily exceed it while waiting for files to be
 * deleted. The limit does not include filesystem overhead or the cache
 * journal so space-sensitive applications should set a conservative limit.
 *
 * <p>Clients call {@link #edit} to create or update the values of an entry. An
 * entry may have only one editor at one time; if a value is not available to be
 * edited then {@link #edit} will return null.
 * <ul>
 *     <li>When an entry is being <strong>created</strong> it is necessary to
 *         supply a full set of values; the empty value should be used as a
 *         placeholder if necessary.
 *     <li>When an entry is being <strong>edited</strong>, it is not necessary
 *         to supply data for every value; values default to their previous
 *         value.
 * </ul>
 * Every {@link #edit} call must be matched by a call to {@link Editor#commit}
 * or {@link Editor#abort}. Committing is atomic: a read observes the full set
 * of values as they were before or after the commit, but never a mix of values.
 *
 * <p>Clients call {@link #get} to read a snapshot of an entry. The read will
 * observe the value at the time that {@link #get} was called. Updates and
 * removals after the call do not impact ongoing reads.
 *
 * <p>This class is tolerant of some I/O errors. If files are missing from the
 * filesystem, the corresponding entries will be dropped from the cache. If
 * an error occurs while writing a cache value, the edit will fail silently.
 * Callers should handle other problems by catching {@code IOException} and
 * responding appropriately.
 */
public final class DiskLruCache implements Closeable {
    static final String JOURNAL_FILE = "journal";
    static final String JOURNAL_FILE_TMP = "journal.tmp";
    static final String MAGIC = "libcore.io.DiskLruCache";
    static final String VERSION_1 = "1";
    static final long ANY_SEQUENCE_NUMBER = -1;
    private static final String CLEAN = "CLEAN";
    private static final String DIRTY = "DIRTY";
    private static final String REMOVE = "REMOVE";
    private static final String READ = "READ";

    private static final Charset UTF_8 = Charset.forName("UTF-8");
    private static final int IO_BUFFER_SIZE = 8 * 1024;

    /*
     * This cache uses a journal file named "journal". A typical journal file
     * looks like this:
     *     libcore.io.DiskLruCache
     *     1
     *     100
     *     2
     *
     *     CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
     *     DIRTY 335c4c6028171cfddfbaae1a9c313c52
     *     CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
     *     REMOVE 335c4c6028171cfddfbaae1a9c313c52
     *     DIRTY 1ab96a171faeeee38496d8b330771a7a
     *     CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
     *     READ 335c4c6028171cfddfbaae1a9c313c52
     *     READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
     *
     * The first five lines of the journal form its header. They are the
     * constant string "libcore.io.DiskLruCache", the disk cache's version,
     * the application's version, the value count, and a blank line.
     *
     * Each of the subsequent lines in the file is a record of the state of a
     * cache entry. Each line contains space-separated values: a state, a key,
     * and optional state-specific values.
     *   o DIRTY lines track that an entry is actively being created or updated.
     *     Every successful DIRTY action should be followed by a CLEAN or REMOVE
     *     action. DIRTY lines without a matching CLEAN or REMOVE indicate that
     *     temporary files may need to be deleted.
     *   o CLEAN lines track a cache entry that has been successfully published
     *     and may be read. A publish line is followed by the lengths of each of
     *     its values.
     *   o READ lines track accesses for LRU.
     *   o REMOVE lines track entries that have been deleted.
     *
     * The journal file is appended to as cache operations occur. The journal may
     * occasionally be compacted by dropping redundant lines. A temporary file named
     * "journal.tmp" will be used during compaction; that file should be deleted if
     * it exists when the cache is opened.
     */

    private final File directory;
    private final File journalFile;
    private final File journalFileTmp;
    private final int appVersion;
    private final long maxSize;
    private final int valueCount;
    private long size = 0;
    private Writer journalWriter;
    private final LinkedHashMap<String, Entry> lruEntries
            = new LinkedHashMap<String, Entry>(0, 0.75f, true);
    private int redundantOpCount;

    /**
     * To differentiate between old and current snapshots, each entry is given
     * a sequence number each time an edit is committed. A snapshot is stale if
     * its sequence number is not equal to its entry's sequence number.
     */
    private long nextSequenceNumber = 0;

    /* From java.util.Arrays */
    @SuppressWarnings("unchecked")
    private static <T> T[] copyOfRange(T[] original, int start, int end) {
        final int originalLength = original.length; // For exception priority compatibility.
        if (start > end) {
            throw new IllegalArgumentException();
        }
        if (start < 0 || start > originalLength) {
            throw new ArrayIndexOutOfBoundsException();
        }
        final int resultLength = end - start;
        final int copyLength = Math.min(resultLength, originalLength - start);
        final T[] result = (T[]) Array
                .newInstance(original.getClass().getComponentType(), resultLength);
        System.arraycopy(original, start, result, 0, copyLength);
        return result;
    }

    /**
     * Returns the remainder of 'reader' as a string, closing it when done.
     */
    public static String readFully(Reader reader) throws IOException {
        try {
            StringWriter writer = new StringWriter();
            char[] buffer = new char[1024];
            int count;
            while ((count = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, count);
            }
            return writer.toString();
        } finally {
            reader.close();
        }
    }

    /**
     * Returns the ASCII characters up to but not including the next "\r\n", or
     * "\n".
     *
     * @throws java.io.EOFException if the stream is exhausted before the next newline
     *     character.
     */
    public static String readAsciiLine(InputStream in) throws IOException {
        // TODO: support UTF-8 here instead

        StringBuilder result = new StringBuilder(80);
        while (true) {
            int c = in.read();
            if (c == -1) {
                throw new EOFException();
            } else if (c == '\n') {
                break;
            }

            result.append((char) c);
        }
        int length = result.length();
        if (length > 0 && result.charAt(length - 1) == '\r') {
            result.setLength(length - 1);
        }
        return result.toString();
    }

    /**
     * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
     */
    public static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (RuntimeException rethrown) {
                throw rethrown;
            } catch (Exception ignored) {
            }
        }
    }

    /**
     * Recursively delete everything in {@code dir}.
     */
    // TODO: this should specify paths as Strings rather than as Files
    public static void deleteContents(File dir) throws IOException {
        File[] files = dir.listFiles();
        if (files == null) {
            throw new IllegalArgumentException("not a directory: " + dir);
        }
        for (File file : files) {
            if (file.isDirectory()) {
                deleteContents(file);
            }
            if (!file.delete()) {
                throw new IOException("failed to delete file: " + file);
            }
        }
    }

    /** This cache uses a single background thread to evict entries. */
    private final ExecutorService executorService = new ThreadPoolExecutor(0, 1,
            60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
    private final Callable<Void> cleanupCallable = new Callable<Void>() {
        @Override public Void call() throws Exception {
            synchronized (DiskLruCache.this) {
                if (journalWriter == null) {
                    return null; // closed
                }
                trimToSize();
                if (journalRebuildRequired()) {
                    rebuildJournal();
                    redundantOpCount = 0;
                }
            }
            return null;
        }
    };

    private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
        this.directory = directory;
        this.appVersion = appVersion;
        this.journalFile = new File(directory, JOURNAL_FILE);
        this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
        this.valueCount = valueCount;
        this.maxSize = maxSize;
    }

    /**
     * Opens the cache in {@code directory}, creating a cache if none exists
     * there.
     *
     * @param directory a writable directory
     * @param appVersion
     * @param valueCount the number of values per cache entry. Must be positive.
     * @param maxSize the maximum number of bytes this cache should use to store
     * @throws java.io.IOException if reading or writing the cache directory fails
     */
    public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
            throws IOException {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0");
        }
        if (valueCount <= 0) {
            throw new IllegalArgumentException("valueCount <= 0");
        }

        // prefer to pick up where we left off
        DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
        if (cache.journalFile.exists()) {
            try {
                cache.readJournal();
                cache.processJournal();
                cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true),
                        IO_BUFFER_SIZE);
                return cache;
            } catch (IOException journalIsCorrupt) {
//                System.logW("DiskLruCache " + directory + " is corrupt: "
//                        + journalIsCorrupt.getMessage() + ", removing");
                cache.delete();
            }
        }

        // create a new empty cache
        directory.mkdirs();
        cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
        cache.rebuildJournal();
        return cache;
    }

    private void readJournal() throws IOException {
        InputStream in = new BufferedInputStream(new FileInputStream(journalFile), IO_BUFFER_SIZE);
        try {
            String magic = readAsciiLine(in);
            String version = readAsciiLine(in);
            String appVersionString = readAsciiLine(in);
            String valueCountString = readAsciiLine(in);
            String blank = readAsciiLine(in);
            if (!MAGIC.equals(magic)
                    || !VERSION_1.equals(version)
                    || !Integer.toString(appVersion).equals(appVersionString)
                    || !Integer.toString(valueCount).equals(valueCountString)
                    || !"".equals(blank)) {
                throw new IOException("unexpected journal header: ["
                        + magic + ", " + version + ", " + valueCountString + ", " + blank + "]");
            }

            while (true) {
                try {
                    readJournalLine(readAsciiLine(in));
                } catch (EOFException endOfJournal) {
                    break;
                }
            }
        } finally {
            closeQuietly(in);
        }
    }

    private void readJournalLine(String line) throws IOException {
        String[] parts = line.split(" ");
        if (parts.length < 2) {
            throw new IOException("unexpected journal line: " + line);
        }

        String key = parts[1];
        if (parts[0].equals(REMOVE) && parts.length == 2) {
            lruEntries.remove(key);
            return;
        }

        Entry entry = lruEntries.get(key);
        if (entry == null) {
            entry = new Entry(key);
            lruEntries.put(key, entry);
        }

        if (parts[0].equals(CLEAN) && parts.length == 2 + valueCount) {
            entry.readable = true;
            entry.currentEditor = null;
            entry.setLengths(copyOfRange(parts, 2, parts.length));
        } else if (parts[0].equals(DIRTY) && parts.length == 2) {
            entry.currentEditor = new Editor(entry);
        } else if (parts[0].equals(READ) && parts.length == 2) {
            // this work was already done by calling lruEntries.get()
        } else {
            throw new IOException("unexpected journal line: " + line);
        }
    }

    /**
     * Computes the initial size and collects garbage as a part of opening the
     * cache. Dirty entries are assumed to be inconsistent and will be deleted.
     */
    private void processJournal() throws IOException {
        deleteIfExists(journalFileTmp);
        for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
            Entry entry = i.next();
            if (entry.currentEditor == null) {
                for (int t = 0; t < valueCount; t++) {
                    size += entry.lengths[t];
                }
            } else {
                entry.currentEditor = null;
                for (int t = 0; t < valueCount; t++) {
                    deleteIfExists(entry.getCleanFile(t));
                    deleteIfExists(entry.getDirtyFile(t));
                }
                i.remove();
            }
        }
    }

    /**
     * Creates a new journal that omits redundant information. This replaces the
     * current journal if it exists.
     */
    private synchronized void rebuildJournal() throws IOException {
        if (journalWriter != null) {
            journalWriter.close();
        }

        Writer writer = new BufferedWriter(new FileWriter(journalFileTmp), IO_BUFFER_SIZE);
        writer.write(MAGIC);
        writer.write("\n");
        writer.write(VERSION_1);
        writer.write("\n");
        writer.write(Integer.toString(appVersion));
        writer.write("\n");
        writer.write(Integer.toString(valueCount));
        writer.write("\n");
        writer.write("\n");

        for (Entry entry : lruEntries.values()) {
            if (entry.currentEditor != null) {
                writer.write(DIRTY + ' ' + entry.key + '\n');
            } else {
                writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
            }
        }

        writer.close();
        journalFileTmp.renameTo(journalFile);
        journalWriter = new BufferedWriter(new FileWriter(journalFile, true), IO_BUFFER_SIZE);
    }

    private static void deleteIfExists(File file) throws IOException {
//        try {
//            Libcore.os.remove(file.getPath());
//        } catch (ErrnoException errnoException) {
//            if (errnoException.errno != OsConstants.ENOENT) {
//                throw errnoException.rethrowAsIOException();
//            }
//        }
        if (file.exists() && !file.delete()) {
            throw new IOException();
        }
    }

    /**
     * Returns a snapshot of the entry named {@code key}, or null if it doesn't
     * exist is not currently readable. If a value is returned, it is moved to
     * the head of the LRU queue.
     */
    public synchronized Snapshot get(String key) throws IOException {
        checkNotClosed();
        validateKey(key);
        Entry entry = lruEntries.get(key);
        if (entry == null) {
            return null;
        }

        if (!entry.readable) {
            return null;
        }

        /*
         * Open all streams eagerly to guarantee that we see a single published
         * snapshot. If we opened streams lazily then the streams could come
         * from different edits.
         */
        InputStream[] ins = new InputStream[valueCount];
        try {
            for (int i = 0; i < valueCount; i++) {
                ins[i] = new FileInputStream(entry.getCleanFile(i));
            }
        } catch (FileNotFoundException e) {
            // a file must have been deleted manually!
            return null;
        }

        redundantOpCount++;
        journalWriter.append(READ + ' ' + key + '\n');
        if (journalRebuildRequired()) {
            executorService.submit(cleanupCallable);
        }

        return new Snapshot(key, entry.sequenceNumber, ins);
    }

    /**
     * Returns an editor for the entry named {@code key}, or null if another
     * edit is in progress.
     */
    public Editor edit(String key) throws IOException {
        return edit(key, ANY_SEQUENCE_NUMBER);
    }

    private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
        checkNotClosed();
        validateKey(key);
        Entry entry = lruEntries.get(key);
        if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER
                && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) {
            return null; // snapshot is stale
        }
        if (entry == null) {
            entry = new Entry(key);
            lruEntries.put(key, entry);
        } else if (entry.currentEditor != null) {
            return null; // another edit is in progress
        }

        Editor editor = new Editor(entry);
        entry.currentEditor = editor;

        // flush the journal before creating files to prevent file leaks
        journalWriter.write(DIRTY + ' ' + key + '\n');
        journalWriter.flush();
        return editor;
    }

    /**
     * Returns the directory where this cache stores its data.
     */
    public File getDirectory() {
        return directory;
    }

    /**
     * Returns the maximum number of bytes that this cache should use to store
     * its data.
     */
    public long maxSize() {
        return maxSize;
    }

    /**
     * Returns the number of bytes currently being used to store the values in
     * this cache. This may be greater than the max size if a background
     * deletion is pending.
     */
    public synchronized long size() {
        return size;
    }

    private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
        Entry entry = editor.entry;
        if (entry.currentEditor != editor) {
            throw new IllegalStateException();
        }

        // if this edit is creating the entry for the first time, every index must have a value
        if (success && !entry.readable) {
            for (int i = 0; i < valueCount; i++) {
                if (!entry.getDirtyFile(i).exists()) {
                    editor.abort();
                    throw new IllegalStateException("edit didn't create file " + i);
                }
            }
        }

        for (int i = 0; i < valueCount; i++) {
            File dirty = entry.getDirtyFile(i);
            if (success) {
                if (dirty.exists()) {
                    File clean = entry.getCleanFile(i);
                    dirty.renameTo(clean);
                    long oldLength = entry.lengths[i];
                    long newLength = clean.length();
                    entry.lengths[i] = newLength;
                    size = size - oldLength + newLength;
                }
            } else {
                deleteIfExists(dirty);
            }
        }

        redundantOpCount++;
        entry.currentEditor = null;
        if (entry.readable | success) {
            entry.readable = true;
            journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
            if (success) {
                entry.sequenceNumber = nextSequenceNumber++;
            }
        } else {
            lruEntries.remove(entry.key);
            journalWriter.write(REMOVE + ' ' + entry.key + '\n');
        }

        if (size > maxSize || journalRebuildRequired()) {
            executorService.submit(cleanupCallable);
        }
    }

    /**
     * We only rebuild the journal when it will halve the size of the journal
     * and eliminate at least 2000 ops.
     */
    private boolean journalRebuildRequired() {
        final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000;
        return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD
                && redundantOpCount >= lruEntries.size();
    }

    /**
     * Drops the entry for {@code key} if it exists and can be removed. Entries
     * actively being edited cannot be removed.
     *
     * @return true if an entry was removed.
     */
    public synchronized boolean remove(String key) throws IOException {
        checkNotClosed();
        validateKey(key);
        Entry entry = lruEntries.get(key);
        if (entry == null || entry.currentEditor != null) {
            return false;
        }

        for (int i = 0; i < valueCount; i++) {
            File file = entry.getCleanFile(i);
            if (!file.delete()) {
                throw new IOException("failed to delete " + file);
            }
            size -= entry.lengths[i];
            entry.lengths[i] = 0;
        }

        redundantOpCount++;
        journalWriter.append(REMOVE + ' ' + key + '\n');
        lruEntries.remove(key);

        if (journalRebuildRequired()) {
            executorService.submit(cleanupCallable);
        }

        return true;
    }

    /**
     * Returns true if this cache has been closed.
     */
    public boolean isClosed() {
        return journalWriter == null;
    }

    private void checkNotClosed() {
        if (journalWriter == null) {
            throw new IllegalStateException("cache is closed");
        }
    }

    /**
     * Force buffered operations to the filesystem.
     */
    public synchronized void flush() throws IOException {
        checkNotClosed();
        trimToSize();
        journalWriter.flush();
    }

    /**
     * Closes this cache. Stored values will remain on the filesystem.
     */
    public synchronized void close() throws IOException {
        if (journalWriter == null) {
            return; // already closed
        }
        for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
            if (entry.currentEditor != null) {
                entry.currentEditor.abort();
            }
        }
        trimToSize();
        journalWriter.close();
        journalWriter = null;
    }

    private void trimToSize() throws IOException {
        while (size > maxSize) {
//            Map.Entry<String, Entry> toEvict = lruEntries.eldest();
            final Map.Entry<String, Entry> toEvict = lruEntries.entrySet().iterator().next();
            remove(toEvict.getKey());
        }
    }

    /**
     * Closes the cache and deletes all of its stored values. This will delete
     * all files in the cache directory including files that weren't created by
     * the cache.
     */
    public void delete() throws IOException {
        close();
        deleteContents(directory);
    }

    private void validateKey(String key) {
        if (key.contains(" ") || key.contains("\n") || key.contains("\r")) {
            throw new IllegalArgumentException(
                    "keys must not contain spaces or newlines: \"" + key + "\"");
        }
    }

    private static String inputStreamToString(InputStream in) throws IOException {
        return readFully(new InputStreamReader(in, UTF_8));
    }

    /**
     * A snapshot of the values for an entry.
     */
    public final class Snapshot implements Closeable {
        private final String key;
        private final long sequenceNumber;
        private final InputStream[] ins;

        private Snapshot(String key, long sequenceNumber, InputStream[] ins) {
            this.key = key;
            this.sequenceNumber = sequenceNumber;
            this.ins = ins;
        }

        /**
         * Returns an editor for this snapshot's entry, or null if either the
         * entry has changed since this snapshot was created or if another edit
         * is in progress.
         */
        public Editor edit() throws IOException {
            return DiskLruCache.this.edit(key, sequenceNumber);
        }

        /**
         * Returns the unbuffered stream with the value for {@code index}.
         */
        public InputStream getInputStream(int index) {
            return ins[index];
        }

        /**
         * Returns the string value for {@code index}.
         */
        public String getString(int index) throws IOException {
            return inputStreamToString(getInputStream(index));
        }

        @Override public void close() {
            for (InputStream in : ins) {
                closeQuietly(in);
            }
        }
    }

    /**
     * Edits the values for an entry.
     */
    public final class Editor {
        private final Entry entry;
        private boolean hasErrors;

        private Editor(Entry entry) {
            this.entry = entry;
        }

        /**
         * Returns an unbuffered input stream to read the last committed value,
         * or null if no value has been committed.
         */
        public InputStream newInputStream(int index) throws IOException {
            synchronized (DiskLruCache.this) {
                if (entry.currentEditor != this) {
                    throw new IllegalStateException();
                }
                if (!entry.readable) {
                    return null;
                }
                return new FileInputStream(entry.getCleanFile(index));
            }
        }

        /**
         * Returns the last committed value as a string, or null if no value
         * has been committed.
         */
        public String getString(int index) throws IOException {
            InputStream in = newInputStream(index);
            return in != null ? inputStreamToString(in) : null;
        }

        /**
         * Returns a new unbuffered output stream to write the value at
         * {@code index}. If the underlying output stream encounters errors
         * when writing to the filesystem, this edit will be aborted when
         * {@link #commit} is called. The returned output stream does not throw
         * IOExceptions.
         */
        public OutputStream newOutputStream(int index) throws IOException {
            synchronized (DiskLruCache.this) {
                if (entry.currentEditor != this) {
                    throw new IllegalStateException();
                }
                return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index)));
            }
        }

        /**
         * Sets the value at {@code index} to {@code value}.
         */
        public void set(int index, String value) throws IOException {
            Writer writer = null;
            try {
                writer = new OutputStreamWriter(newOutputStream(index), UTF_8);
                writer.write(value);
            } finally {
                closeQuietly(writer);
            }
        }

        /**
         * Commits this edit so it is visible to readers.  This releases the
         * edit lock so another edit may be started on the same key.
         */
        public void commit() throws IOException {
            if (hasErrors) {
                completeEdit(this, false);
                remove(entry.key); // the previous entry is stale
            } else {
                completeEdit(this, true);
            }
        }

        /**
         * Aborts this edit. This releases the edit lock so another edit may be
         * started on the same key.
         */
        public void abort() throws IOException {
            completeEdit(this, false);
        }

        private class FaultHidingOutputStream extends FilterOutputStream {
            private FaultHidingOutputStream(OutputStream out) {
                super(out);
            }

            @Override public void write(int oneByte) {
                try {
                    out.write(oneByte);
                } catch (IOException e) {
                    hasErrors = true;
                }
            }

            @Override public void write(byte[] buffer, int offset, int length) {
                try {
                    out.write(buffer, offset, length);
                } catch (IOException e) {
                    hasErrors = true;
                }
            }

            @Override public void close() {
                try {
                    out.close();
                } catch (IOException e) {
                    hasErrors = true;
                }
            }

            @Override public void flush() {
                try {
                    out.flush();
                } catch (IOException e) {
                    hasErrors = true;
                }
            }
        }
    }

    private final class Entry {
        private final String key;

        /** Lengths of this entry's files. */
        private final long[] lengths;

        /** True if this entry has ever been published */
        private boolean readable;

        /** The ongoing edit or null if this entry is not being edited. */
        private Editor currentEditor;

        /** The sequence number of the most recently committed edit to this entry. */
        private long sequenceNumber;

        private Entry(String key) {
            this.key = key;
            this.lengths = new long[valueCount];
        }

        public String getLengths() throws IOException {
            StringBuilder result = new StringBuilder();
            for (long size : lengths) {
                result.append(' ').append(size);
            }
            return result.toString();
        }

        /**
         * Set lengths using decimal numbers like "10123".
         */
        private void setLengths(String[] strings) throws IOException {
            if (strings.length != valueCount) {
                throw invalidLengths(strings);
            }

            try {
                for (int i = 0; i < strings.length; i++) {
                    lengths[i] = Long.parseLong(strings[i]);
                }
            } catch (NumberFormatException e) {
                throw invalidLengths(strings);
            }
        }

        private IOException invalidLengths(String[] strings) throws IOException {
            throw new IOException("unexpected journal line: " + Arrays.toString(strings));
        }

        public File getCleanFile(int i) {
            return new File(directory, key + "." + i);
        }

        public File getDirtyFile(int i) {
            return new File(directory, key + "." + i + ".tmp");
        }
    }
}

 

 

 

 

 

 

DiskLruCacheUtil.java

package net.oschina.app.cache;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import net.oschina.app.util.TDevice;

import org.kymjs.kjframe.utils.FileUtils;

import android.content.Context;
import android.os.Environment;

/**
 * 缓存工具类
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年12月26日 下午4:53:13
 * 
 */

public class DiskLruCacheUtil {

    private static int appVersion = TDevice.getVersionCode();

    private static int valueCount = 1;// 同一个key可以对应多少个缓存文件

    private static int maxSize = 10 * 1024 * 1024;// 一个缓存文件最大可以缓存10M

    public static final String CACHE_OBJECT = "object";// 对象缓存目录

    /**
     * 保存对象缓存
     * 
     * @param context
     * @param ser
     * @param key
     */
    public static void saveObject(Context context, Serializable ser, String key) {
        ObjectOutputStream oos = null;
        try {
            DiskLruCache.Editor editor = getDiskLruCacheOutputStream(context,
                    CACHE_OBJECT, key);
            if (editor != null) {
                oos = new ObjectOutputStream(editor.newOutputStream(0));
                oos.writeObject(ser);
                oos.flush();
                editor.commit();
            }
        } catch (IOException e) {

            e.printStackTrace();
        } finally {
            FileUtils.closeIO(oos);
        }
    }

    /**
     * 读取对象缓存
     * 
     * @param context
     * @param key
     * @return
     */
    public static Serializable readObject(Context context, String key) {
        ObjectInputStream ois = null;
        try {
            DiskLruCache.Editor editor = getDiskLruCacheOutputStream(context,
                    CACHE_OBJECT, key);
            ois = new ObjectInputStream(editor.newInputStream(0));
            return (Serializable) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            FileUtils.closeIO(ois);
        }
        return null;
    }

    /**
     * 获取DiskLruCache的editor
     * 
     * @param context
     * @param key
     * @return
     * @throws IOException
     */
    public static DiskLruCache.Editor getDiskLruCacheOutputStream(
            Context context, String uniqueName, String key) throws IOException {
        DiskLruCache mDiskLruCache = DiskLruCache.open(
                getDiskCacheDir(context, uniqueName), appVersion, valueCount,
                maxSize);
        DiskLruCache.Editor editor = mDiskLruCache.edit(hashKeyForDisk(key));
        return editor;
    }

    /**
     * 获取相应的缓存目录
     * 
     * @param context
     * @param uniqueName
     * @return
     */
    public static File getDiskCacheDir(Context context, String uniqueName) {
        String cachePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }

    /**
     * 传入缓存的key值,以得到相应的MD5值
     * 
     * @param key
     * @return
     */
    public static String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }

    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }
}

 

 

 

 

 

 

DatabaseHelper.java

package net.oschina.app.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * 创建便签的数据库
 * 
 * @author kymjs
 * 
 *         update:2014-01-12 updateor: fireant 内容:修改为全应用数据库
 * 
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String OSC_DATABASE_NAME = "oschina";

    public static final String NOTE_TABLE_NAME = "osc_Notebook";

    public static final String CREATE_NOTE_TABLE = "create table "
            + NOTE_TABLE_NAME
            + " (_id integer primary key autoincrement, iid integer,"
            + " time varchar(10), date varchar(10), content text, color integer)";

    public static final String NEWS_LIST = "osc_news_list";

    public static final String CREATE_NEWS_LIST_TABLE = "create table "
            + NOTE_TABLE_NAME + "(" + "_id integer primary key autoincrement, "
            + "news_id interger, title varchar(10), " + ")";

    public DatabaseHelper(Context context) {
        super(context, OSC_DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_NOTE_TABLE);
        // db.execSQL(CREATE_NEWS_LIST_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}

}

 

 

 

 

 

 

 

NoteDatabase.java

package net.oschina.app.db;

import java.util.ArrayList;
import java.util.List;

import net.oschina.app.bean.NotebookData;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class NoteDatabase {
    private final DatabaseHelper dbHelper;

    public NoteDatabase(Context context) {
        super();
        dbHelper = new DatabaseHelper(context);
    }

    /**
     * 增
     * 
     * @param data
     */
    public void insert(NotebookData data) {
        String sql = "insert into " + DatabaseHelper.NOTE_TABLE_NAME;

        sql += "(_id, iid, time, date, content, color) values(?, ?, ?, ?, ?, ?)";

        SQLiteDatabase sqlite = dbHelper.getWritableDatabase();
        sqlite.execSQL(sql, new String[] { data.getId() + "",
                data.getIid() + "", data.getUnixTime() + "", data.getDate(),
                data.getContent(), data.getColor() + "" });
        sqlite.close();
    }

    /**
     * 删
     * 
     * @param id
     */
    public void delete(int id) {
        SQLiteDatabase sqlite = dbHelper.getWritableDatabase();
        String sql = ("delete from " + DatabaseHelper.NOTE_TABLE_NAME + " where _id=?");
        sqlite.execSQL(sql, new Integer[] { id });
        sqlite.close();
    }

    /**
     * 改
     * 
     * @param data
     */
    public void update(NotebookData data) {
        SQLiteDatabase sqlite = dbHelper.getWritableDatabase();
        String sql = ("update " + DatabaseHelper.NOTE_TABLE_NAME + " set iid=?, time=?, date=?, content=?, color=? where _id=?");
        sqlite.execSQL(sql,
                new String[] { data.getIid() + "", data.getUnixTime() + "",
                        data.getDate(), data.getContent(),
                        data.getColor() + "", data.getId() + "" });
        sqlite.close();
    }

    public List<NotebookData> query() {
        return query(" ");
    }

    /**
     * 查
     * 
     * @param where
     * @return
     */
    public List<NotebookData> query(String where) {
        SQLiteDatabase sqlite = dbHelper.getReadableDatabase();
        ArrayList<NotebookData> data = null;
        data = new ArrayList<NotebookData>();
        Cursor cursor = sqlite.rawQuery("select * from "
                + DatabaseHelper.NOTE_TABLE_NAME + where, null);
        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            NotebookData notebookData = new NotebookData();
            notebookData.setId(cursor.getInt(0));
            notebookData.setIid(cursor.getInt(1));
            notebookData.setUnixTime(cursor.getString(2));
            notebookData.setDate(cursor.getString(3));
            notebookData.setContent(cursor.getString(4));
            notebookData.setColor(cursor.getInt(5));
            data.add(notebookData);
        }
        if (!cursor.isClosed()) {
            cursor.close();
        }
        sqlite.close();

        return data;
    }

    /**
     * 重置
     * 
     * @param datas
     */
    public void reset(List<NotebookData> datas) {
        if (datas != null) {
            SQLiteDatabase sqlite = dbHelper.getWritableDatabase();
            // 删除全部
            sqlite.execSQL("delete from " + DatabaseHelper.NOTE_TABLE_NAME);
            // 重新添加
            for (NotebookData data : datas) {
                insert(data);
            }
            sqlite.close();
        }
    }

    /**
     * 保存一条数据到本地(若已存在则直接覆盖)
     * 
     * @param data
     */
    public void save(NotebookData data) {
        List<NotebookData> datas = query(" where _id=" + data.getId());
        if (datas != null && !datas.isEmpty()) {
            update(data);
        } else {
            insert(data);
        }
    }

    //
    // /**
    // * 合并一条数据到本地(通过更新时间判断仅保留最新)
    // *
    // * @param data
    // * @return 数据是否被合并了
    // */
    // public boolean merge(NotebookData data) {
    // Cursor cursor = sqlite.rawQuery(
    // "select * from " + DatabaseHelper.NOTE_TABLE_NAME
    // + " where _id=" + data.getId(), null);
    // NotebookData localData = new NotebookData();
    // // 本循环其实只执行一次
    // for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
    // localData.setId(cursor.getInt(0));
    // localData.setIid(cursor.getInt(1));
    // localData.setUnixTime(cursor.getString(2));
    // localData.setDate(cursor.getString(3));
    // localData.setContent(cursor.getString(4));
    // localData.setColor(cursor.getInt(5));
    // }
    // // 是否需要合这条数据
    // boolean isMerge = localData.getUnixTime() < data.getUnixTime();
    // if (isMerge) {
    // save(data);
    // }
    // return isMerge;
    // }

    public void destroy() {
        dbHelper.close();
    }
}

 

 

 

 

 

 

ActiveFragment.java

package net.oschina.app.fragment;

import java.io.InputStream;
import java.io.Serializable;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.adapter.ActiveAdapter;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.BaseListFragment;
import net.oschina.app.bean.Active;
import net.oschina.app.bean.ActiveList;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.Notice;
import net.oschina.app.service.NoticeUtils;
import net.oschina.app.ui.MainActivity;
import net.oschina.app.ui.dialog.CommonDialog;
import net.oschina.app.ui.dialog.DialogHelper;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.util.HTMLUtil;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;
import net.oschina.app.viewpagerfragment.NoticeViewPagerFragment;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;

/**
 * 动态fragment
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @author kymjs (https://github.com/kymjs)
 * @created 2014年10月22日 下午3:35:43
 * 
 */
public class ActiveFragment extends BaseListFragment<Active> implements
        OnItemLongClickListener {

    protected static final String TAG = ActiveFragment.class.getSimpleName();
    private static final String CACHE_KEY_PREFIX = "active_list";
    private boolean mIsWatingLogin; // 还没登陆

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (mErrorLayout != null) {
                mIsWatingLogin = true;
                mErrorLayout.setErrorType(EmptyLayout.NETWORK_ERROR);
                mErrorLayout.setErrorMessage(getString(R.string.unlogin_tip));
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        IntentFilter filter = new IntentFilter(Constants.INTENT_ACTION_LOGOUT);
        getActivity().registerReceiver(mReceiver, filter);
    }

    @Override
    public void onDestroy() {
        getActivity().unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    @Override
    public void onResume() {
        if (mIsWatingLogin) {
            mCurrentPage = 0;
            mState = STATE_REFRESH;
            requestData(false);
        }
        refreshNotice();
        super.onResume();
    }

    /**
     * 开始刷新请求
     */
    private void refreshNotice() {
        Notice notice = MainActivity.mNotice;
        if (notice == null) {
            return;
        }
        if (notice.getAtmeCount() > 0 && mCatalog == ActiveList.CATALOG_ATME) {
            onRefresh();
        } else if (notice.getReviewCount() > 0
                && mCatalog == ActiveList.CATALOG_COMMENT) {
            onRefresh();
        }
    }

    @Override
    protected ActiveAdapter getListAdapter() {
        return new ActiveAdapter();
    }

    @Override
    protected String getCacheKeyPrefix() {
        return new StringBuffer(CACHE_KEY_PREFIX + mCatalog).append(
                AppContext.getInstance().getLoginUid()).toString();
    }

    @Override
    protected ActiveList parseList(InputStream is) {
        ActiveList list = XmlUtils.toBean(ActiveList.class, is);
        return list;
    }

    @Override
    protected ActiveList readList(Serializable seri) {
        return ((ActiveList) seri);
    }

    @Override
    public void initView(View view) {
        if (mCatalog == ActiveList.CATALOG_LASTEST) {
            setHasOptionsMenu(true);
        }
        super.initView(view);
        mListView.setOnItemLongClickListener(this);
        mListView.setOnItemClickListener(this);
        mErrorLayout.setOnLayoutClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (AppContext.getInstance().isLogin()) {
                    mErrorLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
                    requestData(false);
                } else {
                    UIHelper.showLoginActivity(getActivity());
                }
            }
        });
        if (AppContext.getInstance().isLogin()) {
            UIHelper.sendBroadcastForNotice(getActivity());
        }
    }

    @Override
    protected void requestData(boolean refresh) {
        if (AppContext.getInstance().isLogin()) {
            mIsWatingLogin = false;
            super.requestData(refresh);
        } else {
            mIsWatingLogin = true;
            mErrorLayout.setErrorType(EmptyLayout.NETWORK_ERROR);
            mErrorLayout.setErrorMessage(getString(R.string.unlogin_tip));
        }
    }

    @Override
    protected void sendRequestData() {
        OSChinaApi.getActiveList(AppContext.getInstance().getLoginUid(),
                mCatalog, mCurrentPage, mHandler);
    }

    @Override
    protected void onRefreshNetworkSuccess() {
        if (AppContext.getInstance().isLogin()) {
            if (0 == NoticeViewPagerFragment.sCurrentPage) {
                NoticeUtils.clearNotice(Notice.TYPE_ATME);
            } else if (1 == NoticeViewPagerFragment.sCurrentPage
                    || NoticeViewPagerFragment.sShowCount[1] > 0) { // 如果当前显示的是评论页,则发送评论页已被查看的Http请求
                NoticeUtils.clearNotice(Notice.TYPE_COMMENT);
            } else {
                NoticeUtils.clearNotice(Notice.TYPE_ATME);
            }
            UIHelper.sendBroadcastForNotice(getActivity());
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        Active active = mAdapter.getItem(position);
        if (active != null)
            UIHelper.showActiveRedirect(view.getContext(), active);
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view,
            int position, long id) {
        final Active active = mAdapter.getItem(position);
        if (active == null)
            return false;
        String[] items = new String[] { getResources().getString(R.string.copy) };
        final CommonDialog dialog = DialogHelper
                .getPinterestDialogCancelable(getActivity());
        dialog.setNegativeButton(R.string.cancle, null);
        dialog.setItemsWithoutChk(items, new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                dialog.dismiss();
                TDevice.copyTextToBoard(HTMLUtil.delHTMLTag(active.getMessage()));
            }
        });
        dialog.show();
        return true;
    }

    @Override
    protected long getAutoRefreshTime() {
        // 最新动态,即是好友圈
        if (mCatalog == ActiveList.CATALOG_LASTEST) {
            return 5 * 60;
        }
        return super.getAutoRefreshTime();
    }
}

 

 

 

 

 

 

EventFragment.java

package net.oschina.app.fragment;

import java.io.InputStream;
import java.io.Serializable;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.adapter.EventAdapter;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.BaseListFragment;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.Event;
import net.oschina.app.bean.EventList;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;

/**
 * 活动列表fragment
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年12月8日 下午5:17:32
 * 
 */
public class EventFragment extends BaseListFragment<Event> {

    public static final String BUNDLE_KEY_EVENT_TYPE = "eventlist_type";

    protected static final String TAG = EventFragment.class.getSimpleName();
    private static final String CACHE_KEY_PREFIX = "eventlist_";

    private int event_type;

    @Override
    protected EventAdapter getListAdapter() {
        EventAdapter adapter = new EventAdapter();
        adapter.setEventType(event_type);
        return adapter;
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            requestData(true);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle args = getArguments();
        if (args != null) {
            event_type = args.getInt(BUNDLE_KEY_EVENT_TYPE);
        }

        if (event_type == EventList.EVENT_LIST_TYPE_MY_EVENT) {
            IntentFilter filter = new IntentFilter(
                    Constants.INTENT_ACTION_USER_CHANGE);
            filter.addAction(Constants.INTENT_ACTION_LOGOUT);
            getActivity().registerReceiver(mReceiver, filter);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (event_type == EventList.EVENT_LIST_TYPE_MY_EVENT) {
            getActivity().unregisterReceiver(mReceiver);
        }
    }

    @Override
    public void initView(View view) {
        super.initView(view);
        mErrorLayout.setOnLayoutClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                clickErrorLayout();
            }
        });
    }

    private void clickErrorLayout() {
        if (event_type == EventList.EVENT_LIST_TYPE_NEW_EVENT) {
            mErrorLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
            requestData(true);
        } else {
            if (AppContext.getInstance().isLogin()) {
                mErrorLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
                requestData(true);
            } else {
                UIHelper.showLoginActivity(getActivity());
            }
        }
    }

    @Override
    protected void requestData(boolean refresh) {

        if (event_type == EventList.EVENT_LIST_TYPE_NEW_EVENT) {
            mCatalog = -1;
            super.requestData(refresh);
            return;
        }
        if (AppContext.getInstance().isLogin()) {
            mCatalog = AppContext.getInstance().getLoginUid();
            super.requestData(refresh);
        } else {
            mErrorLayout.setErrorType(EmptyLayout.NETWORK_ERROR);
            mErrorLayout.setErrorMessage(getString(R.string.unlogin_tip));
        }
    }

    @Override
    protected String getCacheKeyPrefix() {
        return CACHE_KEY_PREFIX + mCatalog;
    }

    @Override
    protected EventList parseList(InputStream is) throws Exception {
        EventList list = XmlUtils.toBean(EventList.class, is);
        return list;
    }

    @Override
    protected EventList readList(Serializable seri) {
        return ((EventList) seri);
    }

    @Override
    protected void sendRequestData() {
        OSChinaApi.getEventList(mCurrentPage, mCatalog, mHandler);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        Event event = mAdapter.getItem(position);
        if (event != null)
            UIHelper.showEventDetail(view.getContext(), event.getId());
    }

}

 

 

 

 

 

EventDetailFragment.java

package net.oschina.app.fragment;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URLEncoder;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.BaseDetailFragment;
import net.oschina.app.base.BaseListFragment;
import net.oschina.app.bean.CommentList;
import net.oschina.app.bean.Entity;
import net.oschina.app.bean.Event;
import net.oschina.app.bean.EventApplyData;
import net.oschina.app.bean.FavoriteList;
import net.oschina.app.bean.Post;
import net.oschina.app.bean.PostDetail;
import net.oschina.app.bean.Result;
import net.oschina.app.bean.ResultBean;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.emoji.OnSendClickListener;
import net.oschina.app.ui.DetailActivity;
import net.oschina.app.ui.EventApplyDialog;
import net.oschina.app.ui.empty.EmptyLayout;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;

import org.apache.http.Header;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

import com.loopj.android.http.AsyncHttpResponseHandler;

/**
 * 活动详情页面
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年12月12日 下午3:08:49
 * 
 */
public class EventDetailFragment extends BaseDetailFragment implements
        OnSendClickListener {

    protected static final String TAG = EventDetailFragment.class
            .getSimpleName();
    private static final String POST_CACHE_KEY = "post_";

    @InjectView(R.id.tv_event_title)
    TextView mTvTitle;

    @InjectView(R.id.tv_event_start_time)
    TextView mTvStartTime;

    @InjectView(R.id.tv_event_end_time)
    TextView mTvEndTime;

    @InjectView(R.id.tv_event_spot)
    TextView mTvSpot;

    @InjectView(R.id.webview)
    WebView mWebView;

    @InjectView(R.id.rl_event_location)
    View mLocation;

    @InjectView(R.id.bt_event_attend)
    Button mBtAttend;// 出席人员

    @InjectView(R.id.bt_event_apply)
    Button mBtEventApply;// 活动报名

    @InjectView(R.id.tv_event_tip)
    TextView mEventTip;

    private int mPostId;
    private Post mPost;

    private EventApplyDialog mEventApplyDialog;

    @Override
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_event_detail, container,
                false);

        mPostId = getActivity().getIntent().getIntExtra("post_id", 0);
        ButterKnife.inject(this, view);
        initViews(view);

        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        requestData(true);
    }

    @Override
    protected void onFavoriteChanged(boolean flag) {
        super.onFavoriteChanged(flag);
        mPost.setFavorite(flag ? 1 : 0);
        saveCache(mPost);
    }

    private void initViews(View view) {
        mEmptyLayout = (EmptyLayout) view.findViewById(R.id.error_layout);

        mLocation.setOnClickListener(this);
        mBtAttend.setOnClickListener(this);
        mBtEventApply.setOnClickListener(this);
        UIHelper.initWebView(mWebView);
    }

    @Override
    public void onClick(View v) {
        super.onClick(v);
        int id = v.getId();
        switch (id) {
        case R.id.rl_event_location:
            UIHelper.showEventLocation(getActivity(), mPost.getEvent()
                    .getCity(), mPost.getEvent().getSpot());
            break;
        case R.id.bt_event_attend:
            showEventApplies();
            break;
        case R.id.bt_event_apply:
            showEventApply();
            break;
        default:
            break;
        }
    }

    private void showEventApplies() {
        Bundle args = new Bundle();
        args.putInt(BaseListFragment.BUNDLE_KEY_CATALOG, mPost.getEvent()
                .getId());
        UIHelper.showSimpleBack(getActivity(), SimpleBackPage.EVENT_APPLY, args);
    }

    private final AsyncHttpResponseHandler mApplyHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            Result rs = XmlUtils.toBean(ResultBean.class,
                    new ByteArrayInputStream(arg2)).getResult();
            if (rs.OK()) {
                AppContext.showToast("报名成功");
                mEventApplyDialog.dismiss();
                mPost.getEvent().setApplyStatus(Event.APPLYSTATUS_CHECKING);
                notifyEventStatus();
            } else {
                AppContext.showToast(rs.getErrorMessage());
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            AppContext.showToast("报名失败");
        }

        @Override
        public void onFinish() {
            hideWaitDialog();
        }
    };

    /**
     * 显示活动报名对话框
     */
    private void showEventApply() {

        if (mPost.getEvent().getCategory() == 4) {
            UIHelper.openSysBrowser(getActivity(), mPost.getEvent().getUrl());
            return;
        }

        if (!AppContext.getInstance().isLogin()) {
            UIHelper.showLoginActivity(getActivity());
            return;
        }
        if (mEventApplyDialog == null) {
            mEventApplyDialog = new EventApplyDialog(getActivity());
            mEventApplyDialog.setCanceledOnTouchOutside(true);
            mEventApplyDialog.setCancelable(true);
            mEventApplyDialog.setTitle("活动报名");
            mEventApplyDialog.setCanceledOnTouchOutside(true);
            mEventApplyDialog.setNegativeButton(R.string.cancle, null);
            mEventApplyDialog.setPositiveButton(R.string.ok,
                    new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface d, int which) {
                            EventApplyData data = null;
                            if ((data = mEventApplyDialog.getApplyData()) != null) {
                                data.setEvent(mPostId);
                                data.setUser(AppContext.getInstance()
                                        .getLoginUid());
                                showWaitDialog(R.string.progress_submit);
                                OSChinaApi.eventApply(data, mApplyHandler);
                            }
                        }
                    });
        }

        mEventApplyDialog.show();
    }

    @Override
    protected String getCacheKey() {
        return new StringBuilder(POST_CACHE_KEY).append(mPostId).toString();
    }

    @Override
    protected void sendRequestData() {
        mEmptyLayout.setErrorType(EmptyLayout.NETWORK_LOADING);
        OSChinaApi.getPostDetail(mPostId, mHandler);
    }

    @Override
    protected Entity parseData(InputStream is) throws Exception {
        return XmlUtils.toBean(PostDetail.class, is).getPost();
    }

    @Override
    protected Entity readData(Serializable seri) {
        return (Post) seri;
    }

    @Override
    protected void executeOnLoadDataSuccess(Entity entity) {
        mPost = (Post) entity;
        fillUI();
        fillWebViewBody();
        ((DetailActivity) getActivity()).toolFragment.setCommentCount(mPost
                .getAnswerCount());
    }

    private void fillUI() {

        mTvTitle.setText(mPost.getTitle());
        mTvStartTime.setText(String.format(
                getString(R.string.event_start_time), mPost.getEvent()
                        .getStartTime()));
        mTvEndTime.setText(String.format(getString(R.string.event_end_time),
                mPost.getEvent().getEndTime()));
        mTvSpot.setText(mPost.getEvent().getCity() + " "
                + mPost.getEvent().getSpot());
        notifyFavorite(mPost.getFavorite() == 1);

        // 站外活动
        if (mPost.getEvent().getCategory() == 4) {
            mBtEventApply.setVisibility(View.VISIBLE);
            mBtAttend.setVisibility(View.GONE);
            mBtEventApply.setText("报名链接");
        } else {
            notifyEventStatus();
        }
    }

    @Override
    public int getCommentCount() {
        return mPost.getAnswerCount();
    }

    // 显示活动 以及报名的状态
    private void notifyEventStatus() {
        int eventStatus = mPost.getEvent().getStatus();
        int applyStatus = mPost.getEvent().getApplyStatus();

        if (applyStatus == Event.APPLYSTATUS_ATTEND) {
            mBtAttend.setVisibility(View.VISIBLE);
        } else {
            mBtAttend.setVisibility(View.GONE);
        }

        if (eventStatus == Event.EVNET_STATUS_APPLYING) {
            mBtEventApply.setVisibility(View.VISIBLE);
            mBtEventApply.setEnabled(false);
            switch (applyStatus) {
            case Event.APPLYSTATUS_CHECKING:
                mBtEventApply.setText("待确认");
                break;
            case Event.APPLYSTATUS_CHECKED:
                mBtEventApply.setText("已确认");
                mBtEventApply.setVisibility(View.GONE);
                mEventTip.setVisibility(View.VISIBLE);
                break;
            case Event.APPLYSTATUS_ATTEND:
                mBtEventApply.setText("已出席");
                break;
            case Event.APPLYSTATUS_CANCLE:
                mBtEventApply.setText("已取消");
                mBtEventApply.setEnabled(true);
                break;
            case Event.APPLYSTATUS_REJECT:
                mBtEventApply.setText("已拒绝");
                break;
            default:
                mBtEventApply.setText("我要报名");
                mBtEventApply.setEnabled(true);
                break;
            }
        } else {
            mBtEventApply.setVisibility(View.GONE);
        }
    }

    private void fillWebViewBody() {
        // 显示标签
        StringBuffer body = new StringBuffer();
        body.append(UIHelper.setHtmlCotentSupportImagePreview(mPost.getBody()));
        body.append(UIHelper.WEB_STYLE).append(UIHelper.WEB_LOAD_IMAGES)
                .append(getPostTags(mPost.getTags()))
                .append("<div style=\"margin-bottom: 80px\" />");
        mWebView.loadDataWithBaseURL(null, body.toString(), "text/html",
                "utf-8", null);
    }

    @SuppressWarnings("deprecation")
    private String getPostTags(Post.Tags taglist) {
        if (taglist == null)
            return "";
        StringBuffer tags = new StringBuffer();
        for (String tag : taglist.getTags()) {
            tags.append(String
                    .format("<a class='tag' href='http://www.oschina.net/question/tag/%s' >&nbsp;%s&nbsp;</a>&nbsp;&nbsp;",
                            URLEncoder.encode(tag), tag));
        }
        return String.format("<div style='margin-top:10px;'>%s</div>", tags);
    }

    @Override
    protected int getFavoriteTargetId() {
        return mPost != null ? mPost.getId() : -1;
    }

    @Override
    protected int getFavoriteTargetType() {
        return mPost != null ? FavoriteList.TYPE_POST : -1;
    }

    @Override
    protected String getShareTitle() {
        return mPost != null ? mPost.getTitle()
                : getString(R.string.share_title_post);
    }

    @Override
    protected String getShareContent() {
        return mPost != null ? StringUtils.getSubString(0, 55,
                getFilterHtmlBody(mPost.getBody())) : "";
    }

    @Override
    protected String getShareUrl() {
        return mPost != null ? mPost.getUrl().replace("http://www", "http://m")
                : null;
    }

    @Override
    public void onClickSendButton(Editable str) {
        if (!TDevice.hasInternet()) {
            AppContext.showToastShort(R.string.tip_network_error);
            return;
        }
        if (!AppContext.getInstance().isLogin()) {
            UIHelper.showLoginActivity(getActivity());
            return;
        }
        if (TextUtils.isEmpty(str)) {
            AppContext.showToastShort(R.string.tip_comment_content_empty);
            return;
        }
        showWaitDialog(R.string.progress_submit);
        OSChinaApi.publicComment(CommentList.CATALOG_POST, mPostId, AppContext
                .getInstance().getLoginUid(), str.toString(), 0,
                mCommentHandler);
    }

    @Override
    public void onClickFlagButton() {}

    @Override
    public void onclickWriteComment() {
        super.onclickWriteComment();
        UIHelper.showComment(getActivity(), mPostId, CommentList.CATALOG_POST);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.refresh_menu, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        sendRequestData();
        return super.onOptionsItemSelected(item);
    }
}

 

 

 

 

 

 

EventAppliesFragment.java

package net.oschina.app.fragment;

import java.io.InputStream;
import java.io.Serializable;

import net.oschina.app.AppContext;
import net.oschina.app.adapter.EventApplyAdapter;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.BaseListFragment;
import net.oschina.app.bean.Apply;
import net.oschina.app.bean.EventAppliesList;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;
import android.annotation.TargetApi;
import android.os.Build;
import android.view.View;
import android.widget.AdapterView;

/**
 * 活动出席人员列表
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年12月12日 下午7:59:10
 *
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class EventAppliesFragment extends BaseListFragment<Apply> {

	protected static final String TAG = EventAppliesFragment.class.getSimpleName();
	private static final String CACHE_KEY_PREFIX = "event_apply_user_list";

	@Override
	public void initView(View view) {
		super.initView(view);
	}

	@Override
	protected EventApplyAdapter getListAdapter() {
		return new EventApplyAdapter();
	}

	@Override
	protected String getCacheKeyPrefix() {
		return CACHE_KEY_PREFIX + "_" + mCatalog;
	}

	@Override
	protected EventAppliesList parseList(InputStream is) throws Exception {
		EventAppliesList list = XmlUtils.toBean(EventAppliesList.class, is);
		return list;
	}

	@Override
	protected EventAppliesList readList(Serializable seri) {
		return ((EventAppliesList) seri);
	}

	@Override
	protected void sendRequestData() {
		OSChinaApi.getEventApplies(mCatalog, mCurrentPage, mHandler);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		Apply item = (Apply) mAdapter.getItem(position);
		if (item != null) {
			if (AppContext.getInstance().isLogin()) {
				UIHelper.showMessageDetail(getActivity(), item.getId(), item.getName());
				return;
			}
			UIHelper.showUserCenter(getActivity(), item.getId(),item.getName());
		}
			
	}
}

 

 

 

 

 

BaseFragmentInterface.java

package net.oschina.app.interf;

import android.view.View;


/**
 * 基类fragment实现接口
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年9月25日 上午11:00:25
 *
 */
public interface BaseFragmentInterface {
	
	public void initView(View view);
	
	public void initData();
}

 

 

 

 

BaseViewInterface.java

package net.oschina.app.interf;

/**
 * 
 * @author deyi
 *
 */
public interface BaseViewInterface {
	
	public void initView();
	
	public void initData();
	
}

 

 

 

 

 

ICallbackResult.java

package net.oschina.app.interf;

/** 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年11月18日 上午11:18:28 
 * 
 */

public interface ICallbackResult {
	
	public void OnBackResult(Object s);
}

 

 

 

 

 

OnTabReselectListener.java

package net.oschina.app.interf;

/** 
 * 当tabHost再次被点击时
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @version 创建时间:2014年11月17日 上午11:00:15 
 * 
 */
public interface OnTabReselectListener {
	
	public void onTabReselect();
}

 

 

 

 

OnWebViewImageListener.java

package net.oschina.app.interf;

/**
 * 监听webview上的图片
 * 
 * @author yeguozhong@yeah.net
 *
 */
public interface OnWebViewImageListener {

	/**
	 * 点击webview上的图片,传入该缩略图的大图Url
	 * @param bigImageUrl
	 */
	void showImagePreview(String bigImageUrl);
	
}

 

 

 

 

 

DownloadService.java

package net.oschina.app.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import net.oschina.app.AppConfig;
import net.oschina.app.R;
import net.oschina.app.interf.ICallbackResult;
import net.oschina.app.ui.MainActivity;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TDevice;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.RemoteViews;

/**
 * download service
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年11月18日 下午3:02:36
 * 
 */
public class DownloadService extends Service {

	public static final String BUNDLE_KEY_DOWNLOAD_URL = "download_url";
	
	public static final String BUNDLE_KEY_TITLE = "title";
	
	private final String tag = "download";
	private static final int NOTIFY_ID = 0;
	private int progress;
	private NotificationManager mNotificationManager;
	private boolean canceled;
	
	private String downloadUrl;
	
	private String mTitle = "正在下载%s";

	private String saveFileName = AppConfig.DEFAULT_SAVE_FILE_PATH;

	private ICallbackResult callback;

	private DownloadBinder binder;

	private boolean serviceIsDestroy = false;

	private Context mContext = this;

	private Thread downLoadThread;

	private Notification mNotification;
	
	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			switch (msg.what) {
			case 0:
				// 下载完毕
				mNotificationManager.cancel(NOTIFY_ID);
				installApk();
				break;
			case 2:
				// 取消通知
				mNotificationManager.cancel(NOTIFY_ID);
				break;
			case 1:
				int rate = msg.arg1;
				if (rate < 100) {
					RemoteViews contentview = mNotification.contentView;
					contentview.setTextViewText(R.id.tv_download_state, mTitle + "(" + rate
							+ "%" + ")");
					contentview.setProgressBar(R.id.pb_download, 100, rate,
							false);
				} else {
					// 下载完毕后变换通知形式
					mNotification.flags = Notification.FLAG_AUTO_CANCEL;
					mNotification.contentView = null;
					Intent intent = new Intent(mContext, MainActivity.class);
					// 告知已完成
					intent.putExtra("completed", "yes");
					// 更新参数,注意flags要使用FLAG_UPDATE_CURRENT
					PendingIntent contentIntent = PendingIntent.getActivity(
							mContext, 0, intent,
							PendingIntent.FLAG_UPDATE_CURRENT);
					mNotification.setLatestEventInfo(mContext, "下载完成",
							"文件已下载完毕", contentIntent);
					serviceIsDestroy = true;
					stopSelf();// 停掉服务自身
				}
				mNotificationManager.notify(NOTIFY_ID, mNotification);
				break;
			}
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		downloadUrl = intent.getStringExtra(BUNDLE_KEY_DOWNLOAD_URL);
		saveFileName = saveFileName + getSaveFileName(downloadUrl); 
		mTitle = String.format(mTitle, intent.getStringExtra(BUNDLE_KEY_TITLE));
		return binder;
	}
	
	private String getSaveFileName(String downloadUrl) {
		if (downloadUrl == null || StringUtils.isEmpty(downloadUrl)) {
			return "";
		}
		return downloadUrl.substring(downloadUrl.lastIndexOf("/"));
	}

	@Override
	public void onCreate() {
		super.onCreate();
		binder = new DownloadBinder();
		mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
		stopForeground(true);// 这个不确定是否有作用
	}

	private void startDownload() {
		canceled = false;
		downloadApk();
	}

	/**
	 * 创建通知
	 */
	private void setUpNotification() {
		int icon = R.drawable.ic_notification;
		CharSequence tickerText = "准备下载";
		long when = System.currentTimeMillis();
		mNotification = new Notification(icon, tickerText, when);
		;
		// 放置在"正在运行"栏目中
		mNotification.flags = Notification.FLAG_ONGOING_EVENT;

		RemoteViews contentView = new RemoteViews(getPackageName(),
				R.layout.download_notification_show);
		contentView.setTextViewText(R.id.tv_download_state, mTitle);
		// 指定个性化视图
		mNotification.contentView = contentView;

		Intent intent = new Intent(this, MainActivity.class);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				intent, PendingIntent.FLAG_UPDATE_CURRENT);

		// 指定内容意图
		mNotification.contentIntent = contentIntent;
		mNotificationManager.notify(NOTIFY_ID, mNotification);
	}

	private void downloadApk() {
		downLoadThread = new Thread(mdownApkRunnable);
		downLoadThread.start();
	}

	/**
	 * 安装apk
	 */
	private void installApk() {
		File apkfile = new File(saveFileName);
		if (!apkfile.exists()) {
			return;
		}
		TDevice.installAPK(mContext, apkfile);
	}

	private Runnable mdownApkRunnable = new Runnable() {
		@Override
		public void run() {
			File file = new File(AppConfig.DEFAULT_SAVE_FILE_PATH);
			if (!file.exists()) {
				file.mkdirs();
			}
			String apkFile = saveFileName;
			File saveFile = new File(apkFile);
			try {
				downloadUpdateFile(downloadUrl, saveFile);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};

	public long downloadUpdateFile(String downloadUrl, File saveFile)
			throws Exception {
		int downloadCount = 0;
		int currentSize = 0;
		long totalSize = 0;
		int updateTotalSize = 0;

		HttpURLConnection httpConnection = null;
		InputStream is = null;
		FileOutputStream fos = null;

		try {
			URL url = new URL(downloadUrl);
			httpConnection = (HttpURLConnection) url.openConnection();
			httpConnection
					.setRequestProperty("User-Agent", "PacificHttpClient");
			if (currentSize > 0) {
				httpConnection.setRequestProperty("RANGE", "bytes="
						+ currentSize + "-");
			}
			httpConnection.setConnectTimeout(10000);
			httpConnection.setReadTimeout(20000);
			updateTotalSize = httpConnection.getContentLength();
			if (httpConnection.getResponseCode() == 404) {
				throw new Exception("fail!");
			}
			is = httpConnection.getInputStream();
			fos = new FileOutputStream(saveFile, false);
			byte buffer[] = new byte[1024];
			int readsize = 0;
			while ((readsize = is.read(buffer)) > 0) {
				fos.write(buffer, 0, readsize);
				totalSize += readsize;
				// 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次
				if ((downloadCount == 0)
						|| (int) (totalSize * 100 / updateTotalSize) - 10 >= downloadCount) {
					downloadCount += 10;
					// 更新进度
					Message msg = mHandler.obtainMessage();
					msg.what = 1;
					msg.arg1 = downloadCount;
						mHandler.sendMessage(msg);
						if (callback != null)
							callback.OnBackResult(progress);
				}
			}
			
			// 下载完成通知安装
			mHandler.sendEmptyMessage(0);
			// 下载完了,cancelled也要设置
			canceled = true;
			
		} finally {
			if (httpConnection != null) {
				httpConnection.disconnect();
			}
			if (is != null) {
				is.close();
			}
			if (fos != null) {
				fos.close();
			}
		}
		return totalSize;
	}

	public class DownloadBinder extends Binder {
		public void start() {
			if (downLoadThread == null || !downLoadThread.isAlive()) {
				progress = 0;
				setUpNotification();
				new Thread() {
					public void run() {
						// 下载
						startDownload();
					};
				}.start();
			}
		}

		public void cancel() {
			canceled = true;
		}

		public int getProgress() {
			return progress;
		}

		public boolean isCanceled() {
			return canceled;
		}

		public boolean serviceIsDestroy() {
			return serviceIsDestroy;
		}

		public void cancelNotification() {
			mHandler.sendEmptyMessage(2);
		}

		public void addCallback(ICallbackResult callback) {
			DownloadService.this.callback = callback;
		}
	}
}

 

 

 

 

 

 

NoticeService.java

package net.oschina.app.service;

import java.io.ByteArrayInputStream;
import java.lang.ref.WeakReference;

import net.oschina.app.AppConfig;
import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.Notice;
import net.oschina.app.bean.NoticeDetail;
import net.oschina.app.bean.Result;
import net.oschina.app.bean.ResultBean;
import net.oschina.app.broadcast.AlarmReceiver;
import net.oschina.app.ui.MainActivity;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.XmlUtils;

import org.apache.http.Header;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;

import com.loopj.android.http.AsyncHttpResponseHandler;

public class NoticeService extends Service {
    public static final String INTENT_ACTION_GET = "net.oschina.app.service.GET_NOTICE";
    public static final String INTENT_ACTION_CLEAR = "net.oschina.app.service.CLEAR_NOTICE";
    public static final String INTENT_ACTION_BROADCAST = "net.oschina.app.service.BROADCAST";
    public static final String INTENT_ACTION_SHUTDOWN = "net.oschina.app.service.SHUTDOWN";
    public static final String INTENT_ACTION_REQUEST = "net.oschina.app.service.REQUEST";
    public static final String BUNDLE_KEY_TPYE = "bundle_key_type";

    private static final long INTERVAL = 1000 * 120;
    private AlarmManager mAlarmMgr;

    private Notice mNotice;

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Constants.INTENT_ACTION_NOTICE.equals(action)) {
        	Notice notice = (Notice) intent.getSerializableExtra("notice_bean");
                int atmeCount = notice.getAtmeCount();// @我
                int msgCount = notice.getMsgCount();// 留言
                int reviewCount = notice.getReviewCount();// 评论
                int newFansCount = notice.getNewFansCount();// 新粉丝
                int newLikeCount = notice.getNewLikeCount();// 点赞数
                int activeCount = atmeCount + reviewCount + msgCount
                        + newFansCount + newLikeCount;
                if (activeCount == 0) {
                    NotificationManagerCompat.from(NoticeService.this).cancel(
                            R.string.you_have_news_messages);
                }
            } else if (INTENT_ACTION_BROADCAST.equals(action)) {
                if (mNotice != null) {
                    UIHelper.sendBroadCast(NoticeService.this, mNotice);
                }
            } else if (INTENT_ACTION_SHUTDOWN.equals(action)) {
                stopSelf();
            } else if (INTENT_ACTION_REQUEST.equals(action)) {
                requestNotice();
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mAlarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);
        startRequestAlarm();
        requestNotice();

        IntentFilter filter = new IntentFilter(INTENT_ACTION_BROADCAST);
        filter.addAction(Constants.INTENT_ACTION_NOTICE);
        filter.addAction(INTENT_ACTION_SHUTDOWN);
        filter.addAction(INTENT_ACTION_REQUEST);
        registerReceiver(mReceiver, filter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        cancelRequestAlarm();
        unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private void startRequestAlarm() {
        cancelRequestAlarm();
        // 从1秒后开始,每隔2分钟执行getOperationIntent()
        mAlarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
                System.currentTimeMillis() + 1000, INTERVAL,
                getOperationIntent());
    }

    /**
     * <!-- kymjs --> 即使启动PendingIntent的原进程结束了的话,PendingIntent本身仍然还存在,可在其他进程(
     * PendingIntent被递交到的其他程序)中继续使用.
     * 如果我在从系统中提取一个PendingIntent的,而系统中有一个和你描述的PendingIntent对等的PendingInent,
     * 那么系统会直接返回和该PendingIntent其实是同一token的PendingIntent,
     * 而不是一个新的token和PendingIntent。然而你在从提取PendingIntent时,通过FLAG_CANCEL_CURRENT参数,
     * 让这个老PendingIntent的先cancel()掉,这样得到的pendingInten和其token的就是新的了。
     */
    private void cancelRequestAlarm() {
        mAlarmMgr.cancel(getOperationIntent());
    }

    /**
     * OSC采用轮询方式实现消息推送<br>
     * 每次被调用都去执行一次{@link #AlarmReceiver}onReceive()方法
     * 
     * @return
     */
    private PendingIntent getOperationIntent() {
        Intent intent = new Intent(this, AlarmReceiver.class);
        PendingIntent operation = PendingIntent.getBroadcast(this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        return operation;
    }

    private void clearNotice(int uid, int type) {
        OSChinaApi.clearNotice(uid, type, mClearNoticeHandler);
    }

    private int lastNotifiyCount;

    private void notification(Notice notice) {
        int atmeCount = notice.getAtmeCount();
        int msgCount = notice.getMsgCount();
        int reviewCount = notice.getReviewCount();
        int newFansCount = notice.getNewFansCount();
        int newLikeCount = notice.getNewLikeCount();

        int count = atmeCount + msgCount + reviewCount + newFansCount + newLikeCount;

        if (count == 0) {
            lastNotifiyCount = 0;
            NotificationManagerCompat.from(this).cancel(
                    R.string.you_have_news_messages);
            return;
        }
        if (count == lastNotifiyCount)
            return;

        lastNotifiyCount = count;

        Resources res = getResources();
        String contentTitle = res.getString(R.string.you_have_news_messages,
                count);
        String contentText;
        StringBuffer sb = new StringBuffer();
        if (atmeCount > 0) {
            sb.append(getString(R.string.atme_count, atmeCount)).append(" ");
        }
        if (msgCount > 0) {
            sb.append(getString(R.string.msg_count, msgCount)).append(" ");
        }
        if (reviewCount > 0) {
            sb.append(getString(R.string.review_count, reviewCount))
                    .append(" ");
        }
        if (newFansCount > 0) {
            sb.append(getString(R.string.fans_count, newFansCount));
        }
        if (newLikeCount > 0) {
            sb.append(getString(R.string.like_count, newLikeCount));
        }
        contentText = sb.toString();

        Intent intent = new Intent(this, MainActivity.class);
        intent.putExtra("NOTICE", true);

        PendingIntent pi = PendingIntent.getActivity(this, 1000, intent,
                PendingIntent.FLAG_CANCEL_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                this).setTicker(contentTitle).setContentTitle(contentTitle)
                .setContentText(contentText).setAutoCancel(true)
                .setContentIntent(pi).setSmallIcon(R.drawable.ic_notification);

        if (AppContext.get(AppConfig.KEY_NOTIFICATION_SOUND, true)) {
            builder.setSound(Uri.parse("android.resource://"
                    + AppContext.getInstance().getPackageName() + "/"
                    + R.raw.notificationsound));
        }
        if (AppContext.get(AppConfig.KEY_NOTIFICATION_VIBRATION, true)) {
            long[] vibrate = { 0, 10, 20, 30 };
            builder.setVibrate(vibrate);
        }

        Notification notification = builder.build();

        NotificationManagerCompat.from(this).notify(
                R.string.you_have_news_messages, notification);
    }

    private final AsyncHttpResponseHandler mGetNoticeHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                Notice notice = XmlUtils.toBean(NoticeDetail.class,
                	arg2).getNotice();
                if (notice != null) {
                    UIHelper.sendBroadCast(NoticeService.this, notice);
                    if (AppContext.get(AppConfig.KEY_NOTIFICATION_ACCEPT, true)) {
                        notification(notice);
                    }
                    mNotice = notice;
                } else {
//                    ResultBean resultBean = XmlUtils.toBean(ResultBean.class, arg2);
//                    if (resultBean != null && resultBean.getResult() != null) {
//                	AppContext appContext = AppContext.getInstance();
//                	if (appContext != null) {
//                	    appContext.Logout();
//                	}
//                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        };

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            arg3.printStackTrace();
        }
    };

    private final AsyncHttpResponseHandler mClearNoticeHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                ResultBean rsb = XmlUtils.toBean(ResultBean.class,
                        new ByteArrayInputStream(arg2));
                Result res = rsb.getResult();
                if (res.OK() && rsb.getNotice() != null) {
                    mNotice = rsb.getNotice();
                    UIHelper.sendBroadCast(NoticeService.this, rsb.getNotice());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {}
    };

    /**
     * 请求是否有新通知
     */
    private void requestNotice() {
        OSChinaApi.getNotices(mGetNoticeHandler);
    }

    private static class ServiceStub extends INoticeService.Stub {
        WeakReference<NoticeService> mService;

        ServiceStub(NoticeService service) {
            mService = new WeakReference<NoticeService>(service);
        }

        @Override
        public void clearNotice(int uid, int type) throws RemoteException {
            mService.get().clearNotice(uid, type);
        }

        @Override
        public void scheduleNotice() throws RemoteException {
            mService.get().startRequestAlarm();
        }

        @Override
        public void requestNotice() throws RemoteException {
            mService.get().requestNotice();
        }
    }

    private final IBinder mBinder = new ServiceStub(this);
}

 

 

 

 

 

 

NoticeUtils.java

package net.oschina.app.service;

import java.util.HashMap;

import net.oschina.app.AppConfig;
import net.oschina.app.AppContext;
import net.oschina.app.util.TLog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.RemoteException;
import android.util.Log;

public class NoticeUtils {

    public static INoticeService sService = null;
    private static HashMap<Context, ServiceBinder> sConnectionMap = new HashMap<Context, ServiceBinder>();

    public static boolean bindToService(Context context) {
        return bindToService(context, null);
    }

    public static boolean bindToService(Context context,
            ServiceConnection callback) {
        context.startService(new Intent(context, NoticeService.class));
        ServiceBinder sb = new ServiceBinder(callback);
        sConnectionMap.put(context, sb);
        return context.bindService(
                (new Intent()).setClass(context, NoticeService.class), sb, 0);
    }

    public static void unbindFromService(Context context) {
        ServiceBinder sb = sConnectionMap.remove(context);
        if (sb == null) {
            Log.e("MusicUtils", "Trying to unbind for unknown Context");
            return;
        }
        context.unbindService(sb);
        if (sConnectionMap.isEmpty()) {
            // presumably there is nobody interested in the service at this
            // point,
            // so don't hang on to the ServiceConnection
            sService = null;
        }
    }

    public static void clearNotice(int type) {
        if (sService != null) {
            try {
                sService.clearNotice(AppContext.getInstance().getLoginUid(),
                        type);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public static void requestNotice(Context context) {
        if (sService != null) {
            try {
                TLog.log("requestNotice...");
                sService.requestNotice();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        } else {
            context.sendBroadcast(new Intent(
                    NoticeService.INTENT_ACTION_REQUEST));
            TLog.log("requestNotice,service is null");
        }
    }

    public static void scheduleNotice() {
        if (sService != null) {
            try {
                sService.scheduleNotice();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    private static class ServiceBinder implements ServiceConnection {
        ServiceConnection mCallback;

        ServiceBinder(ServiceConnection callback) {
            mCallback = callback;
        }

        @Override
        public void onServiceConnected(ComponentName className,
                android.os.IBinder service) {
            sService = INoticeService.Stub.asInterface(service);
            if (mCallback != null) {
                mCallback.onServiceConnected(className, service);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (mCallback != null) {
                mCallback.onServiceDisconnected(className);
            }
            sService = null;
        }
    }

    public static void tryToShutDown(Context context) {
        if (AppContext.get(AppConfig.KEY_NOTIFICATION_DISABLE_WHEN_EXIT, true)) {
            context.sendBroadcast(new Intent(
                    NoticeService.INTENT_ACTION_SHUTDOWN));
        }
    }

    public static void startNotifyService(Context context) {
        Intent service = new Intent(context, NoticeService.class);
        context.startService(service);
    }
}

 

 

 

 

 

 

 

 

 

PublicCommentTask.java

package net.oschina.app.service;

import android.os.Parcel;
import android.os.Parcelable;

public class PublicCommentTask implements Parcelable {
	private int catalog;
	private int id;
	private int uid;
	private String content;
	private int isPostToMyZone;

	public PublicCommentTask() {
	}

	public PublicCommentTask(Parcel source) {
		catalog = source.readInt();
		id = source.readInt();
		uid = source.readInt();
		content = source.readString();
		isPostToMyZone = source.readInt();
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(catalog);
		dest.writeInt(id);
		dest.writeInt(uid);
		dest.writeString(content);
		dest.writeInt(isPostToMyZone);
	}

	public int getCatalog() {
		return catalog;
	}

	public void setCatalog(int catalog) {
		this.catalog = catalog;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getUid() {
		return uid;
	}

	public void setUid(int uid) {
		this.uid = uid;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public int getIsPostToMyZone() {
		return isPostToMyZone;
	}

	public void setIsPostToMyZone(int isPostToMyZone) {
		this.isPostToMyZone = isPostToMyZone;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	public static final Parcelable.Creator<PublicCommentTask> CREATOR = new Creator<PublicCommentTask>() {

		@Override
		public PublicCommentTask[] newArray(int size) {
			return new PublicCommentTask[size];
		}

		@Override
		public PublicCommentTask createFromParcel(Parcel source) {
			return new PublicCommentTask(source);
		}
	};
}

 

 

 

 

 

 

ServerTaskService.java

package net.oschina.app.service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.api.OperationResponseHandler;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.bean.Comment;
import net.oschina.app.bean.Result;
import net.oschina.app.bean.ResultBean;
import net.oschina.app.bean.Tweet;
import net.oschina.app.util.XmlUtils;
import android.app.IntentService;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;

public class ServerTaskService extends IntentService {
    private static final String SERVICE_NAME = "ServerTaskService";
    public static final String ACTION_PUB_BLOG_COMMENT = "net.oschina.app.ACTION_PUB_BLOG_COMMENT";
    public static final String ACTION_PUB_COMMENT = "net.oschina.app.ACTION_PUB_COMMENT";
    public static final String ACTION_PUB_POST = "net.oschina.app.ACTION_PUB_POST";
    public static final String ACTION_PUB_TWEET = "net.oschina.app.ACTION_PUB_TWEET";
    public static final String ACTION_PUB_SOFTWARE_TWEET = "net.oschina.app.ACTION_PUB_SOFTWARE_TWEET";

    public static final String KEY_ADAPTER = "adapter";

    public static final String BUNDLE_PUB_COMMENT_TASK = "BUNDLE_PUB_COMMENT_TASK";
    public static final String BUNDLE_PUB_POST_TASK = "BUNDLE_PUB_POST_TASK";
    public static final String BUNDLE_PUB_TWEET_TASK = "BUNDLE_PUB_TWEET_TASK";
    public static final String BUNDLE_PUB_SOFTWARE_TWEET_TASK = "BUNDLE_PUB_SOFTWARE_TWEET_TASK";
    public static final String KEY_SOFTID = "soft_id";

    private static final String KEY_COMMENT = "comment_";
    private static final String KEY_TWEET = "tweet_";
    private static final String KEY_SOFTWARE_TWEET = "software_tweet_";
    private static final String KEY_POST = "post_";

    public static List<String> penddingTasks = new ArrayList<String>();

    class PublicCommentResponseHandler extends OperationResponseHandler {

	public PublicCommentResponseHandler(Looper looper, Object... args) {
	    super(looper, args);
	}

	@Override
	public void onSuccess(int code, ByteArrayInputStream is, Object[] args)
		throws Exception {
	    PublicCommentTask task = (PublicCommentTask) args[0];
	    final int id = task.getId() * task.getUid();
	    ResultBean resB = XmlUtils.toBean(ResultBean.class, is);
	    Result res = resB.getResult();
	    if (res.OK()) {
		final Comment comment = resB.getComment();
		// UIHelper.sendBroadCastCommentChanged(ServerTaskService.this,
		// isBlog, task.getId(), task.getCatalog(),
		// Comment.OPT_ADD, comment);
		notifySimpleNotifycation(id,
			getString(R.string.comment_publish_success),
			getString(R.string.comment_blog),
			getString(R.string.comment_publish_success), false,
			true);
		removePenddingTask(KEY_COMMENT + id);
	    } else {
		onFailure(100, res.getErrorMessage(), args);
	    }
	}

	@Override
	public void onFailure(int code, String errorMessage, Object[] args) {
	    PublicCommentTask task = (PublicCommentTask) args[0];
	    int id = task.getId() * task.getUid();
	    notifySimpleNotifycation(id,
		    getString(R.string.comment_publish_faile),
		    getString(R.string.comment_blog),
		    code == 100 ? errorMessage
			    : getString(R.string.comment_publish_faile), false,
		    true);
	    removePenddingTask(KEY_COMMENT + id);
	}

	@Override
	public void onFinish() {
	    tryToStopServie();
	}
    }

    class PublicTweetResponseHandler extends OperationResponseHandler {

	String key = null;

	public PublicTweetResponseHandler(Looper looper, Object... args) {
	    super(looper, args);
	    key = (String) args[1];
	}

	@Override
	public void onSuccess(int code, ByteArrayInputStream is, Object[] args)
		throws Exception {
	    Tweet tweet = (Tweet) args[0];
	    final int id = tweet.getId();
	    Result res = XmlUtils.toBean(ResultBean.class, is).getResult();
	    if (res.OK()) {
		notifySimpleNotifycation(id,
			getString(R.string.tweet_publish_success),
			getString(R.string.tweet_public),
			getString(R.string.tweet_publish_success), false, true);
		new Handler().postDelayed(new Runnable() {
		    @Override
		    public void run() {
			cancellNotification(id);
		    }
		}, 3000);
		removePenddingTask(key + id);
		if (tweet.getImageFilePath() != null) {
		    File imgFile = new File(tweet.getImageFilePath());
		    if (imgFile.exists()) {
			imgFile.delete();
		    }
		}
	    } else {
		onFailure(100, res.getErrorMessage(), args);
	    }
	}

	@Override
	public void onFailure(int code, String errorMessage, Object[] args) {
	    Tweet tweet = (Tweet) args[0];
	    int id = tweet.getId();
	    notifySimpleNotifycation(id,
		    getString(R.string.tweet_publish_faile),
		    getString(R.string.tweet_public),
		    code == 100 ? errorMessage
			    : getString(R.string.tweet_publish_faile), false,
		    true);
	    removePenddingTask(key + id);
	}

	@Override
	public void onFinish() {
	    tryToStopServie();
	}
    }

    public ServerTaskService() {
	this(SERVICE_NAME);
    }

    private synchronized void tryToStopServie() {
	if (penddingTasks == null || penddingTasks.size() == 0) {
	    stopSelf();
	}
    }

    private synchronized void addPenddingTask(String key) {
	penddingTasks.add(key);
    }

    private synchronized void removePenddingTask(String key) {
	penddingTasks.remove(key);
    }

    public ServerTaskService(String name) {
	super(name);
    }

    @Override
    public void onCreate() {
	super.onCreate();

    }

    @Override
    protected void onHandleIntent(Intent intent) {
	String action = intent.getAction();

	if (ACTION_PUB_BLOG_COMMENT.equals(action)) {
	    PublicCommentTask task = intent
		    .getParcelableExtra(BUNDLE_PUB_COMMENT_TASK);
	    if (task != null) {
		publicBlogComment(task);
	    }
	} else if (ACTION_PUB_COMMENT.equals(action)) {
	    PublicCommentTask task = intent
		    .getParcelableExtra(BUNDLE_PUB_COMMENT_TASK);
	    if (task != null) {
		publicComment(task);
	    }
	} else if (ACTION_PUB_POST.equals(action)) {
	    // Post post = intent.getParcelableExtra(BUNDLE_PUBLIC_POST_TASK);
	    // if (post != null) {
	    // publicPost(post);
	    // }
	} else if (ACTION_PUB_TWEET.equals(action)) {
	    Tweet tweet = intent.getParcelableExtra(BUNDLE_PUB_TWEET_TASK);
	    if (tweet != null) {
		pubTweet(tweet);
	    }
	} else if (ACTION_PUB_SOFTWARE_TWEET.equals(action)) {
	    Tweet tweet = intent
		    .getParcelableExtra(BUNDLE_PUB_SOFTWARE_TWEET_TASK);
	    int softid = intent.getIntExtra(KEY_SOFTID, -1);
	    if (tweet != null && softid != -1) {
		pubSoftWareTweet(tweet, softid);
	    }
	}
    }

    private void publicBlogComment(final PublicCommentTask task) {
	int id = task.getId() * task.getUid();
	addPenddingTask(KEY_COMMENT + id);

	notifySimpleNotifycation(id, getString(R.string.comment_publishing),
		getString(R.string.comment_blog),
		getString(R.string.comment_publishing), true, false);

	OSChinaApi.publicBlogComment(task.getId(), task.getUid(), task
		.getContent(), new PublicCommentResponseHandler(
		getMainLooper(), task, true));
    }

    private void publicComment(final PublicCommentTask task) {
	int id = task.getId() * task.getUid();
	addPenddingTask(KEY_COMMENT + id);

	notifySimpleNotifycation(id, getString(R.string.comment_publishing),
		getString(R.string.comment_blog),
		getString(R.string.comment_publishing), true, false);

	OSChinaApi.publicComment(task.getCatalog(), task.getId(),
		task.getUid(), task.getContent(), task.getIsPostToMyZone(),
		new PublicCommentResponseHandler(getMainLooper(), task, false));
    }

    // private void publicPost(Post post) {
    // post.setId((int) System.currentTimeMillis());
    // int id = post.getId();
    // addPenddingTask(KEY_POST + id);
    // notifySimpleNotifycation(id, getString(R.string.post_publishing),
    // getString(R.string.post_public),
    // getString(R.string.post_publishing), true, false);
    // OSChinaApi.publicPost(post, new
    // PublicPostResponseHandler(getMainLooper(),
    // post));
    // }
    //
    private void pubTweet(final Tweet tweet) {
	tweet.setId((int) System.currentTimeMillis());
	int id = tweet.getId();
	addPenddingTask(KEY_TWEET + id);
	notifySimpleNotifycation(id, getString(R.string.tweet_publishing),
		getString(R.string.tweet_public),
		getString(R.string.tweet_publishing), true, false);
	OSChinaApi.pubTweet(tweet, new PublicTweetResponseHandler(
		getMainLooper(), tweet, KEY_TWEET));
    }

    private void pubSoftWareTweet(final Tweet tweet, int softid) {
	tweet.setId((int) System.currentTimeMillis());
	int id = tweet.getId();
	addPenddingTask(KEY_SOFTWARE_TWEET + id);
	notifySimpleNotifycation(id, getString(R.string.tweet_publishing),
		getString(R.string.tweet_public),
		getString(R.string.tweet_publishing), true, false);
	OSChinaApi.pubSoftWareTweet(tweet, softid,
		new PublicTweetResponseHandler(getMainLooper(), tweet,
			KEY_SOFTWARE_TWEET));
    }

    private void notifySimpleNotifycation(int id, String ticker, String title,
	    String content, boolean ongoing, boolean autoCancel) {
	NotificationCompat.Builder builder = new NotificationCompat.Builder(
		this)
		.setTicker(ticker)
		.setContentTitle(title)
		.setContentText(content)
		.setAutoCancel(true)
		.setOngoing(false)
		.setOnlyAlertOnce(true)
		.setContentIntent(
			PendingIntent.getActivity(this, 0, new Intent(), 0))
		.setSmallIcon(R.drawable.ic_notification);

	// if (AppContext.isNotificationSoundEnable()) {
	// builder.setDefaults(Notification.DEFAULT_SOUND);
	// }

	Notification notification = builder.build();

	NotificationManagerCompat.from(this).notify(id, notification);
    }

    private void cancellNotification(int id) {
	NotificationManagerCompat.from(this).cancel(id);
    }
}

 

 

 

 

 

 

 

ServerTaskUtils.java

package net.oschina.app.service;

import net.oschina.app.bean.Tweet;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

public class ServerTaskUtils {

    public static void publicBlogComment(Context context, PublicCommentTask task) {
	Intent intent = new Intent(ServerTaskService.ACTION_PUB_BLOG_COMMENT);
	Bundle bundle = new Bundle();
	bundle.putParcelable(ServerTaskService.BUNDLE_PUB_COMMENT_TASK, task);
	intent.putExtras(bundle);
	context.startService(intent);
    }

    public static void publicNewsComment(Context context, PublicCommentTask task) {
	Intent intent = new Intent(ServerTaskService.ACTION_PUB_COMMENT);
	Bundle bundle = new Bundle();
	bundle.putParcelable(ServerTaskService.BUNDLE_PUB_COMMENT_TASK, task);
	intent.putExtras(bundle);
	context.startService(intent);
    }

    public static void pubTweet(Context context, Tweet tweet) {
	Intent intent = new Intent(ServerTaskService.ACTION_PUB_TWEET);
	Bundle bundle = new Bundle();
	bundle.putParcelable(ServerTaskService.BUNDLE_PUB_TWEET_TASK, tweet);
	intent.putExtras(bundle);
	context.startService(intent);
    }

    public static void pubSoftWareTweet(Context context, Tweet tweet, int softid) {
	Intent intent = new Intent(ServerTaskService.ACTION_PUB_SOFTWARE_TWEET);
	Bundle bundle = new Bundle();
	bundle.putParcelable(ServerTaskService.BUNDLE_PUB_SOFTWARE_TWEET_TASK,
		tweet);
	bundle.putInt(ServerTaskService.KEY_SOFTID, softid);
	intent.putExtras(bundle);
	context.startService(intent);
    }

    public static void pubTweetComment(Context context, PublicCommentTask task) {
	Intent intent = new Intent(ServerTaskService.ACTION_PUB_COMMENT);
	Bundle bundle = new Bundle();
	bundle.putParcelable(ServerTaskService.BUNDLE_PUB_COMMENT_TASK, task);
	intent.putExtras(bundle);
	context.startService(intent);
    }
}

 

 

 

 

 

 

 

DynamicAdapter.java

package net.oschina.app.team.adapter;

import net.oschina.app.R;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.team.bean.TeamActive;
import net.oschina.app.ui.ImagePreviewActivity;
import net.oschina.app.util.StringUtils;
import net.oschina.app.widget.AvatarView;
import net.oschina.app.widget.TweetTextView;

import org.kymjs.kjframe.KJBitmap;
import org.kymjs.kjframe.bitmap.BitmapCallBack;
import org.kymjs.kjframe.bitmap.BitmapHelper;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Team动态界面ListView适配器 (kymjs123@gmail.com)
 * 
 * @author kymjs (https://github.com/kymjs)
 * 
 */
public class DynamicAdapter extends ListBaseAdapter<TeamActive> {
    private final Context context;
    private final KJBitmap kjb = new KJBitmap();

    public DynamicAdapter(Context cxt) {
        this.context = cxt;
    }

    static class ViewHolder {
        AvatarView img_head;
        TextView tv_name;
        TweetTextView tv_content;
        TextView tv_client;
        TextView tv_date;
        TextView tv_commit;
        TextView tv_title;
        ImageView iv_pic;
    }

    @Override
    protected View getRealView(int position, View v, ViewGroup parent) {
        super.getRealView(position, v, parent);
        ViewHolder holder = null;
        TeamActive data = mDatas.get(position);
        if (v == null || v.getTag() == null) {
            v = View.inflate(context, R.layout.list_cell_team_active, null);
            holder = new ViewHolder();
            holder.img_head = (AvatarView) v
                    .findViewById(R.id.event_listitem_userface);
            holder.tv_name = (TextView) v
                    .findViewById(R.id.event_listitem_username);
            holder.tv_title = (TextView) v.findViewById(R.id.title);
            holder.tv_content = (TweetTextView) v
                    .findViewById(R.id.event_listitem_content);
            holder.tv_client = (TextView) v
                    .findViewById(R.id.event_listitem_client);
            holder.iv_pic = (ImageView) v.findViewById(R.id.iv_pic);
            holder.tv_date = (TextView) v
                    .findViewById(R.id.event_listitem_date);
            holder.tv_commit = (TextView) v.findViewById(R.id.tv_comment_count);
            v.setTag(holder);
        } else {
            holder = (ViewHolder) v.getTag();
        }
        holder.img_head.setAvatarUrl(data.getAuthor().getPortrait());
        holder.img_head.setUserInfo(data.getAuthor().getId(), data.getAuthor()
                .getName());
        holder.tv_name.setText(data.getAuthor().getName());
        setContent(holder.tv_content, stripTags(data.getBody().getTitle()));

        String date = StringUtils.friendly_time2(data.getCreateTime());
        String preDate = "";
        if (position > 0) {
            preDate = StringUtils.friendly_time2(mDatas.get(position - 1)
                    .getCreateTime());
        }
        if (preDate.equals(date)) {
            holder.tv_title.setVisibility(View.GONE);
        } else {
            holder.tv_title.setText(date);
            holder.tv_title.setVisibility(View.VISIBLE);
        }

        holder.tv_content.setMaxLines(3);
        holder.tv_date.setText(StringUtils.friendly_time(data.getCreateTime()));
        holder.tv_commit.setText(data.getReply());
        String imgPath = data.getBody().getImage();
        if (!StringUtils.isEmpty(imgPath)) {
            holder.iv_pic.setVisibility(View.VISIBLE);
            setTweetImage(holder.iv_pic, imgPath);
        } else {
            holder.iv_pic.setVisibility(View.GONE);
        }
        return v;
    }

    /**
     * 移除字符串中的Html标签
     * 
     * @author kymjs (https://github.com/kymjs)
     * @param pHTMLString
     * @return
     */
    public static String stripTags(final String pHTMLString) {
        // String str = pHTMLString.replaceAll("\\<.*?>", "");
        String str = pHTMLString.replaceAll("\\t", "");
        str = str.replaceAll("<\\s*img\\s+([^>]*)\\s*>", "").trim();
        return str;
    }

    @Override
    public TeamActive getItem(int arg0) {
        super.getItem(arg0);
        return mDatas.get(arg0);
    }

    /**
     * 动态设置图片显示样式
     * 
     * @author kymjs
     */
    private void setTweetImage(final ImageView pic, final String url) {
        pic.setVisibility(View.VISIBLE);

        kjb.display(pic, url, R.drawable.pic_bg, 0, 0, new BitmapCallBack() {
            @Override
            public void onSuccess(Bitmap bitmap) {
                super.onSuccess(bitmap);
                if (bitmap != null) {
                    bitmap = BitmapHelper.scaleWithXY(bitmap,
                            360 / bitmap.getHeight());
                    pic.setImageBitmap(bitmap);
                }
            }
        });

        pic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ImagePreviewActivity.showImagePrivew(context, 0,
                        new String[] { url });
            }
        });
    }
}

 

 

 

 

 

 

 

 

DiaryPagerAdapter.java

package net.oschina.app.team.adapter;

import net.oschina.app.util.StringUtils;
import net.oschina.app.widget.DiaryPageContentView;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

/**
 * 周报ViewPager适配器
 * 
 * @author kymjs (http://www.kymjs.com)
 */
public class DiaryPagerAdapter extends PagerAdapter {
    private final Context cxt;
    private final int currentYear;
    private final int teamId;

    public DiaryPagerAdapter(Context cxt, int currentYear, int teamId) {
        this.currentYear = currentYear;
        this.cxt = cxt;
        this.teamId = teamId;
    }

    @Override
    public int getCount() {
        return currentYear == 2015 ? StringUtils.getWeekOfYear() : 52;
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View pagerView = new DiaryPageContentView(cxt, teamId, currentYear,
                position + 1).getView();
        (container).addView(pagerView);
        return pagerView;
    }
}

 

 

 

 

 

 

 

TeamDiscussAdapter.java

package net.oschina.app.team.adapter;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.base.ListBaseAdapter;
import net.oschina.app.team.bean.TeamDiscuss;
import net.oschina.app.util.HTMLUtil;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TypefaceUtils;
import net.oschina.app.widget.AvatarView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

/**
 * team 讨论区帖子
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年10月9日 下午6:22:54
 * 
 */
public class TeamDiscussAdapter extends ListBaseAdapter<TeamDiscuss> {

    static class ViewHolder {

	@InjectView(R.id.tv_title)
	TextView title;
	@InjectView(R.id.tv_description)
	TextView description;
	@InjectView(R.id.tv_author)
	TextView author;
	@InjectView(R.id.tv_date)
	TextView time;
	@InjectView(R.id.tv_count)
	TextView comment_count;
	@InjectView(R.id.tv_vote_up)
	TextView vote_up;

	@InjectView(R.id.iv_face)
	public AvatarView face;

	public ViewHolder(View view) {
	    ButterKnife.inject(this, view);
	}
    }

    @Override
    protected View getRealView(int position, View convertView, ViewGroup parent) {
	ViewHolder vh = null;
	if (convertView == null || convertView.getTag() == null) {
	    convertView = getLayoutInflater(parent.getContext()).inflate(
		    R.layout.list_cell_team_discuss, null);
	    vh = new ViewHolder(convertView);
	    convertView.setTag(vh);
	} else {
	    vh = (ViewHolder) convertView.getTag();
	}

	TeamDiscuss item = mDatas.get(position);

	vh.face.setUserInfo(item.getAuthor().getId(), item.getAuthor()
		.getName());
	vh.face.setAvatarUrl(item.getAuthor().getPortrait());
	vh.title.setText(item.getTitle());
	String body = item.getBody().trim();
	vh.description.setVisibility(View.GONE);
	if (null != body || !StringUtils.isEmpty(body)) {
	    vh.description.setVisibility(View.VISIBLE);
	    vh.description.setText(HTMLUtil.replaceTag(item.getBody()).trim());
	}
	TypefaceUtils.setTypeface(vh.author, item.getAuthor().getName());
	String faTime = AppContext.getInstance().getResources().getString(R.string.fa_clock_o);
	TypefaceUtils.setTypeface(vh.time, faTime + " " + StringUtils.friendly_time(item.getCreateTime()));
	String faVoteUp = AppContext.getInstance().getResources().getString(R.string.fa_thumbs_o_up);
	TypefaceUtils.setTypeface(vh.vote_up, faVoteUp + " " + item.getVoteUp());
	String commentCount = AppContext.getInstance().getResources().getString(R.string.fa_comment);
	TypefaceUtils.setTypeface(vh.comment_count, commentCount + " " + item.getAnswerCount());
	return convertView;
    }
}

 

 

 

 

 

 

MainActivity.java

package net.oschina.app.ui;

import net.oschina.app.AppConfig;
import net.oschina.app.AppContext;
import net.oschina.app.AppManager;
import net.oschina.app.R;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.Notice;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.cache.DataCleanManager;
import net.oschina.app.fragment.MyInformationFragment;
import net.oschina.app.interf.BaseViewInterface;
import net.oschina.app.interf.OnTabReselectListener;
import net.oschina.app.service.NoticeUtils;
import net.oschina.app.util.UIHelper;
import net.oschina.app.util.UpdateManager;
import net.oschina.app.widget.BadgeView;
import net.oschina.app.widget.MyFragmentTabHost;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TabHost.TabContentFactory;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
import butterknife.ButterKnife;
import butterknife.InjectView;

import com.networkbench.agent.impl.NBSAppAgent;

@SuppressLint("InflateParams")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends ActionBarActivity implements
        NavigationDrawerFragment.NavigationDrawerCallbacks,
        OnTabChangeListener, BaseViewInterface, View.OnClickListener,
        OnTouchListener {

    private DoubleClickExitHelper mDoubleClickExit;

    /**
     * Fragment managing the behaviors, interactions and presentation of the
     * navigation drawer.
     */
    private NavigationDrawerFragment mNavigationDrawerFragment;

    @InjectView(android.R.id.tabhost)
    public MyFragmentTabHost mTabHost;

    private BadgeView mBvNotice;

    public static Notice mNotice;

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Constants.INTENT_ACTION_NOTICE)) {
                mNotice = (Notice) intent.getSerializableExtra("notice_bean");
                int atmeCount = mNotice.getAtmeCount();// @我
                int msgCount = mNotice.getMsgCount();// 留言
                int reviewCount = mNotice.getReviewCount();// 评论
                int newFansCount = mNotice.getNewFansCount();// 新粉丝
                int newLikeCount = mNotice.getNewLikeCount();// 收到赞
                int activeCount = atmeCount + reviewCount + msgCount
                        + newFansCount + newLikeCount;

                Fragment fragment = getCurrentFragment();
                if (fragment instanceof MyInformationFragment) {
                    ((MyInformationFragment) fragment).setNotice();
                } else {
                    if (activeCount > 0) {
                        mBvNotice.setText(activeCount + "");
                        mBvNotice.show();
                    } else {
                        mBvNotice.hide();
                        mNotice = null;
                    }
                }
            } else if (intent.getAction()
                    .equals(Constants.INTENT_ACTION_LOGOUT)) {
                mBvNotice.hide();
                mNotice = null;
            }
        }
    };

    /**
     * Used to store the last screen title. For use in
     * {@link #restoreActionBar()}.
     */
    private CharSequence mTitle;

    @InjectView(R.id.quick_option_iv)
    View mAddBt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        initView();
        AppManager.getAppManager().addActivity(this);

        handleIntent(getIntent());
        // 注册听云的检测分析
        NBSAppAgent.setLicenseKey("0ed0cc66c5cb45c0a91c6fa932ca99ac")
                .withCrashReportEnabled(true).withLocationServiceEnabled(true)
                .start(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    /**
     * 处理传进来的intent
     * 
     * @author 火蚁 2015-1-28 下午3:48:44
     * 
     * @return void
     * @param intent
     */
    private void handleIntent(Intent intent) {
        if (intent == null)
            return;
        String action = intent.getAction();
        if (action != null && action.equals(Intent.ACTION_VIEW)) {
            UIHelper.showUrlRedirect(this, intent.getDataString());
        } else if (intent.getBooleanExtra("NOTICE", false)) {
            notifitcationBarClick(intent);
        }
    }

    /**
     * 从通知栏点击的时候相应
     * 
     * @param fromWhich
     */
    private void notifitcationBarClick(Intent fromWhich) {
        if (fromWhich != null) {
            boolean fromNoticeBar = fromWhich.getBooleanExtra("NOTICE", false);
            if (fromNoticeBar) {
                Intent toMyInfor = new Intent(this, SimpleBackActivity.class);
                toMyInfor.putExtra(SimpleBackActivity.BUNDLE_KEY_PAGE,
                        SimpleBackPage.MY_MES.getValue());
                startActivity(toMyInfor);
            }
        }
    }

    @Override
    public void initView() {
        mDoubleClickExit = new DoubleClickExitHelper(this);
        mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
                .findFragmentById(R.id.navigation_drawer);
        mTitle = getTitle();

        // Set up the drawer.
        mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
                (DrawerLayout) findViewById(R.id.drawer_layout));

        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
        if (android.os.Build.VERSION.SDK_INT > 10) {
            mTabHost.getTabWidget().setShowDividers(0);
        }

        initTabs();

        // 中间按键图片触发
        mAddBt.setOnClickListener(this);

        mTabHost.setCurrentTab(0);
        mTabHost.setOnTabChangedListener(this);

        IntentFilter filter = new IntentFilter(Constants.INTENT_ACTION_NOTICE);
        filter.addAction(Constants.INTENT_ACTION_LOGOUT);
        registerReceiver(mReceiver, filter);
        NoticeUtils.bindToService(this);

        if (AppContext.isFristStart()) {
            mNavigationDrawerFragment.openDrawerMenu();
            DataCleanManager.cleanInternalCache(AppContext.getInstance());
            AppContext.setFristStart(false);
        }

        checkUpdate();
    }

    private void checkUpdate() {
        if (!AppContext.get(AppConfig.KEY_CHECK_UPDATE, true)) {
            return;
        }
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                new UpdateManager(MainActivity.this, false).checkUpdate();
            }
        }, 2000);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NoticeUtils.unbindFromService(this);
        unregisterReceiver(mReceiver);
        mReceiver = null;
        NoticeUtils.tryToShutDown(this);
    }

    @Override
    public void initData() {

    }

    private void initTabs() {
        MainTab[] tabs = MainTab.values();
        final int size = tabs.length;
        for (int i = 0; i < size; i++) {
            MainTab mainTab = tabs[i];
            TabSpec tab = mTabHost.newTabSpec(getString(mainTab.getResName()));
            View indicator = LayoutInflater.from(getApplicationContext())
                    .inflate(R.layout.tab_indicator, null);
            TextView title = (TextView) indicator.findViewById(R.id.tab_title);
            Drawable drawable = this.getResources().getDrawable(
                    mainTab.getResIcon());
            title.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null,
                    null);
            if (i == 2) {
                indicator.setVisibility(View.INVISIBLE);
                mTabHost.setNoTabChangedTag(getString(mainTab.getResName()));
            }
            title.setText(getString(mainTab.getResName()));
            tab.setIndicator(indicator);
            tab.setContent(new TabContentFactory() {

                @Override
                public View createTabContent(String tag) {
                    return new View(MainActivity.this);
                }
            });
            mTabHost.addTab(tab, mainTab.getClz(), null);

            if (mainTab.equals(MainTab.ME)) {
                View cn = indicator.findViewById(R.id.tab_mes);
                mBvNotice = new BadgeView(MainActivity.this, cn);
                mBvNotice.setBadgePosition(BadgeView.POSITION_TOP_RIGHT);
                mBvNotice.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
                mBvNotice.setBackgroundResource(R.drawable.notification_bg);
                mBvNotice.setGravity(Gravity.CENTER);
            }
            mTabHost.getTabWidget().getChildAt(i).setOnTouchListener(this);
        }
    }

    @Override
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
    }

    public void restoreActionBar() {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        actionBar.setDisplayShowTitleEnabled(true);
        actionBar.setTitle(mTitle);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_activity_menu, menu);
        if (!mNavigationDrawerFragment.isDrawerOpen()) {
            restoreActionBar();
            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
        case R.id.search:
            UIHelper.showSimpleBack(this, SimpleBackPage.SEARCH);
            break;

        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabChanged(String tabId) {
        final int size = mTabHost.getTabWidget().getTabCount();
        for (int i = 0; i < size; i++) {
            View v = mTabHost.getTabWidget().getChildAt(i);
            if (i == mTabHost.getCurrentTab()) {
                v.setSelected(true);
            } else {
                v.setSelected(false);
            }
        }
        if (tabId.equals(getString(MainTab.ME.getResName()))) {
            mBvNotice.setText("");
            mBvNotice.hide();
        }
        supportInvalidateOptionsMenu();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
        // 点击了快速操作按钮
        case R.id.quick_option_iv:
            showQuickOption();
            break;

        default:
            break;
        }
    }

    // 显示快速操作界面
    private void showQuickOption() {
        final QuickOptionDialog dialog = new QuickOptionDialog(
                MainActivity.this);
        dialog.setCancelable(true);
        dialog.setCanceledOnTouchOutside(true);
        dialog.show();
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        super.onTouchEvent(event);
        boolean consumed = false;
        // use getTabHost().getCurrentTabView to decide if the current tab is
        // touched again
        if (event.getAction() == MotionEvent.ACTION_DOWN
                && v.equals(mTabHost.getCurrentTabView())) {
            // use getTabHost().getCurrentView() to get a handle to the view
            // which is displayed in the tab - and to get this views context
            Fragment currentFragment = getCurrentFragment();
            if (currentFragment != null
                    && currentFragment instanceof OnTabReselectListener) {
                OnTabReselectListener listener = (OnTabReselectListener) currentFragment;
                listener.onTabReselect();
                consumed = true;
            }
        }
        return consumed;
    }

    private Fragment getCurrentFragment() {
        return getSupportFragmentManager().findFragmentByTag(
                mTabHost.getCurrentTabTag());
    }

    /**
     * 监听返回--是否退出程序
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // 是否退出应用
            if (AppContext.get(AppConfig.KEY_DOUBLE_CLICK_EXIT, true)) {
                return mDoubleClickExit.onKeyDown(keyCode, event);
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        // 当 API Level > 11 调用这个方法可能导致奔溃(android.os.Build.VERSION.SDK_INT > 11)
    }
}

 

 

 

 

 

MainTab.java

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.fragment.ExploreFragment;
import net.oschina.app.fragment.MyInformationFragment;
import net.oschina.app.viewpagerfragment.NewsViewPagerFragment;
import net.oschina.app.viewpagerfragment.TweetsViewPagerFragment;

public enum MainTab {

	NEWS(0, R.string.main_tab_name_news, R.drawable.tab_icon_new,
			NewsViewPagerFragment.class),

	TWEET(1, R.string.main_tab_name_tweet, R.drawable.tab_icon_tweet,
			TweetsViewPagerFragment.class),

	QUICK(2, R.string.main_tab_name_quick, R.drawable.tab_icon_new,
			null),

	EXPLORE(3, R.string.main_tab_name_explore, R.drawable.tab_icon_explore,
			ExploreFragment.class),

	ME(4, R.string.main_tab_name_my, R.drawable.tab_icon_me,
			MyInformationFragment.class);

	private int idx;
	private int resName;
	private int resIcon;
	private Class<?> clz;

	private MainTab(int idx, int resName, int resIcon, Class<?> clz) {
		this.idx = idx;
		this.resName = resName;
		this.resIcon = resIcon;
		this.clz = clz;
	}

	public int getIdx() {
		return idx;
	}

	public void setIdx(int idx) {
		this.idx = idx;
	}

	public int getResName() {
		return resName;
	}

	public void setResName(int resName) {
		this.resName = resName;
	}

	public int getResIcon() {
		return resIcon;
	}

	public void setResIcon(int resIcon) {
		this.resIcon = resIcon;
	}

	public Class<?> getClz() {
		return clz;
	}

	public void setClz(Class<?> clz) {
		this.clz = clz;
	}
}

 

 

 

 

 

DetailActivity.java

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.base.BaseActivity;
import net.oschina.app.base.BaseDetailFragment;
import net.oschina.app.base.BaseFragment;
import net.oschina.app.emoji.KJEmojiFragment;
import net.oschina.app.emoji.OnSendClickListener;
import net.oschina.app.emoji.ToolbarFragment;
import net.oschina.app.emoji.ToolbarFragment.OnActionClickListener;
import net.oschina.app.emoji.ToolbarFragment.ToolAction;
import net.oschina.app.fragment.BlogDetailFragment;
import net.oschina.app.fragment.EventDetailFragment;
import net.oschina.app.fragment.NewsDetailFragment;
import net.oschina.app.fragment.PostDetailFragment;
import net.oschina.app.fragment.SoftwareDetailFragment;
import net.oschina.app.fragment.TweetDetailFragment;
import net.oschina.app.team.fragment.TeamDiaryDetail;
import net.oschina.app.team.fragment.TeamDiscussDetailFragment;
import net.oschina.app.team.fragment.TeamIssueDetailFragment;
import net.oschina.app.team.fragment.TeamTweetDetailFragment;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;

/**
 * 详情activity(包括:资讯、博客、软件、问答、动弹)
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年10月11日 上午11:18:41
 * 
 */
public class DetailActivity extends BaseActivity implements OnSendClickListener {

    public static final int DISPLAY_NEWS = 0;
    public static final int DISPLAY_BLOG = 1;
    public static final int DISPLAY_SOFTWARE = 2;
    public static final int DISPLAY_POST = 3;
    public static final int DISPLAY_TWEET = 4;
    public static final int DISPLAY_EVENT = 5;
    public static final int DISPLAY_TEAM_ISSUE_DETAIL = 6;
    public static final int DISPLAY_TEAM_DISCUSS_DETAIL = 7;
    public static final int DISPLAY_TEAM_TWEET_DETAIL = 8;
    public static final int DISPLAY_TEAM_DIARY = 9;

    public static final String BUNDLE_KEY_DISPLAY_TYPE = "BUNDLE_KEY_DISPLAY_TYPE";

    private OnSendClickListener currentFragment;
    public KJEmojiFragment emojiFragment = new KJEmojiFragment();
    public ToolbarFragment toolFragment = new ToolbarFragment();

    @Override
    protected int getLayoutId() {
        return R.layout.activity_detail;
    }

    @Override
    protected boolean hasBackButton() {
        return true;
    }

    @Override
    protected int getActionBarTitle() {
        return R.string.actionbar_title_detail;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        super.init(savedInstanceState);
        int displayType = getIntent().getIntExtra(BUNDLE_KEY_DISPLAY_TYPE,
                DISPLAY_NEWS);
        BaseFragment fragment = null;
        int actionBarTitle = 0;
        switch (displayType) {
        case DISPLAY_NEWS:
            actionBarTitle = R.string.actionbar_title_news;
            fragment = new NewsDetailFragment();
            break;
        case DISPLAY_BLOG:
            actionBarTitle = R.string.actionbar_title_blog;
            fragment = new BlogDetailFragment();
            break;
        case DISPLAY_SOFTWARE:
            actionBarTitle = R.string.actionbar_title_software;
            fragment = new SoftwareDetailFragment();
            break;
        case DISPLAY_POST:
            actionBarTitle = R.string.actionbar_title_question;
            fragment = new PostDetailFragment();
            break;
        case DISPLAY_TWEET:
            actionBarTitle = R.string.actionbar_title_tweet;
            fragment = new TweetDetailFragment();
            break;
        case DISPLAY_EVENT:
            actionBarTitle = R.string.actionbar_title_event_detail;
            fragment = new EventDetailFragment();
            break;
        case DISPLAY_TEAM_ISSUE_DETAIL:
            actionBarTitle = R.string.team_issue_detail;
            fragment = new TeamIssueDetailFragment();
            break;
        case DISPLAY_TEAM_DISCUSS_DETAIL:
            actionBarTitle = R.string.actionbar_title_question;
            fragment = new TeamDiscussDetailFragment();
            break;
        case DISPLAY_TEAM_TWEET_DETAIL:
            actionBarTitle = R.string.actionbar_dynamic_detail;
            fragment = new TeamTweetDetailFragment();
            break;
        case DISPLAY_TEAM_DIARY:
            actionBarTitle = R.string.team_diary_detail;
            fragment = new TeamDiaryDetail();
            break;
        default:
            break;
        }
        setActionBarTitle(actionBarTitle);
        FragmentTransaction trans = getSupportFragmentManager()
                .beginTransaction();
        trans.replace(R.id.container, fragment);
        trans.commitAllowingStateLoss();
        if (fragment instanceof OnSendClickListener) {
            currentFragment = (OnSendClickListener) fragment;
        } else {
            currentFragment = new OnSendClickListener() {
                @Override
                public void onClickSendButton(Editable str) {}

                @Override
                public void onClickFlagButton() {}
            };
        }
    }

    @Override
    public void onClick(View v) {}

    @Override
    public void initView() {
        if (currentFragment instanceof TweetDetailFragment
                || currentFragment instanceof TeamTweetDetailFragment
                || currentFragment instanceof TeamDiaryDetail
                || currentFragment instanceof TeamIssueDetailFragment
                || currentFragment instanceof TeamDiscussDetailFragment) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.emoji_keyboard, emojiFragment).commit();
        } else {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.emoji_keyboard, toolFragment).commit();
        }
        toolFragment.setOnActionClickListener(new OnActionClickListener() {
            @Override
            public void onActionClick(ToolAction action) {
                switch (action) {
                case ACTION_CHANGE:
                case ACTION_WRITE_COMMENT:
                    getSupportFragmentManager()
                            .beginTransaction()
                            .setCustomAnimations(R.anim.footer_menu_slide_in,
                                    R.anim.footer_menu_slide_out)
                            .replace(R.id.emoji_keyboard, emojiFragment)
                            .commit();
                    break;
                case ACTION_FAVORITE:
                    ((BaseDetailFragment) currentFragment)
                            .handleFavoriteOrNot();
                    break;
                case ACTION_REPORT:
                    ((BaseDetailFragment) currentFragment).onReportMenuClick();
                    break;
                case ACTION_SHARE:
                    ((BaseDetailFragment) currentFragment).handleShare();
                    break;
                case ACTION_VIEW_COMMENT:
                    ((BaseDetailFragment) currentFragment)
                            .onclickWriteComment();
                    break;
                default:
                    break;
                }
            }
        });

    }

    @Override
    public void initData() {}

    @Override
    public void onClickSendButton(Editable str) {
        currentFragment.onClickSendButton(str);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            try {
                if (emojiFragment.isShowEmojiKeyBoard()) {
                    emojiFragment.hideAllKeyBoard();
                    return true;
                }
                if (emojiFragment.getEditText().getTag() != null) {
                    emojiFragment.getEditText().setTag(null);
                    emojiFragment.getEditText().setHint("说点什么吧");
                    return true;
                }
            } catch (NullPointerException e) {
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    public void setCommentCount(int count) {
        try {
            toolFragment.setCommentCount(count);
        } catch (Exception e) {
        }
    }

    @Override
    public void onClickFlagButton() {
        getSupportFragmentManager()
                .beginTransaction()
                .setCustomAnimations(R.anim.footer_menu_slide_in,
                        R.anim.footer_menu_slide_out)
                .replace(R.id.emoji_keyboard, toolFragment).commit();
        try {
            toolFragment.setCommentCount(((BaseDetailFragment) currentFragment)
                    .getCommentCount());
        } catch (Exception e) {
        }
    }
}

 

 

 

 

 

 

 

DoubleClickExitHelper.java

package net.oschina.app.ui;

import net.oschina.app.AppManager;
import net.oschina.app.R;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.view.KeyEvent;
import android.widget.Toast;


/***
 * 双击退出
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2015年1月5日 下午7:07:44
 *
 */
public class DoubleClickExitHelper {

	private final Activity mActivity;
	
	private boolean isOnKeyBacking;
	private Handler mHandler;
	private Toast mBackToast;
	
	public DoubleClickExitHelper(Activity activity) {
		mActivity = activity;
		mHandler = new Handler(Looper.getMainLooper());
	}
	
	/**
	 * Activity onKeyDown事件
	 * */
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode != KeyEvent.KEYCODE_BACK) {
			return false;
		}
		if(isOnKeyBacking) {
			mHandler.removeCallbacks(onBackTimeRunnable);
			if(mBackToast != null){
				mBackToast.cancel();
			}
			// 退出
			AppManager.getAppManager().AppExit(mActivity);
			return true;
		} else {
			isOnKeyBacking = true;
			if(mBackToast == null) {
				mBackToast = Toast.makeText(mActivity, R.string.tip_double_click_exit, 2000);
			}
			mBackToast.show();
			mHandler.postDelayed(onBackTimeRunnable, 2000);
			return true;
		}
	}
	
	private Runnable onBackTimeRunnable = new Runnable() {
		
		@Override
		public void run() {
			isOnKeyBacking = false;
			if(mBackToast != null){
				mBackToast.cancel();
			}
		}
	};
}

 

 

 

 

 

 

EventLocationActivity.java

package net.oschina.app.ui;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.base.BaseActivity;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.navi.BaiduMapAppNotSupportNaviException;
import com.baidu.mapapi.navi.BaiduMapNavigation;
import com.baidu.mapapi.navi.NaviPara;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeOption;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;

/**
 * 活动地图位置显示
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年12月15日 下午1:28:28
 * 
 */
@SuppressLint("InflateParams")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class EventLocationActivity extends BaseActivity implements
		OnGetGeoCoderResultListener {

	GeoCoder mSearch = null; // 搜索模块,也可去掉地图模块独立使用
	BaiduMap mBaiduMap = null;
	MapView mMapView = null;

	private String mCity;

	private String mLocation;

	@Override
	protected boolean hasBackButton() {
		return true;
	}

	@Override
	protected int getActionBarTitle() {
		return R.string.actionbar_title_event_location;
	}

	protected void onCreate(Bundle savedInstanceState) {
		SDKInitializer.initialize(getApplicationContext());
		super.onCreate(savedInstanceState);
	}

	@Override
	protected int getLayoutId() {
		return R.layout.fragment_event_location;
	}

	@Override
	protected void onPause() {
		mMapView.onPause();
		super.onPause();
	}

	@Override
	protected void onResume() {
		mMapView.onResume();
		super.onResume();
	}

	@Override
	protected void onDestroy() {
		mMapView.onDestroy();
		mSearch.destroy();
		super.onDestroy();
	}

	@Override
	public void onGetGeoCodeResult(GeoCodeResult result) {
		if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
			AppContext.showToast("抱歉,未能找到结果");
			return;
		}
		mBaiduMap.clear();

		final LatLng location = result.getLocation();

		final Marker marker = (Marker) mBaiduMap
				.addOverlay(new MarkerOptions()
						.position(location)
						.icon(BitmapDescriptorFactory
								.fromResource(R.drawable.icon_gcoding))
						.draggable(true));
		mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(result
				.getLocation()));

		MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(14.0f);
		mBaiduMap.setMapStatus(msu);

		View view = mInflater.inflate(R.layout.event_spot_pupwindow, null,
				false);

		TextView spot = (TextView) view.findViewById(R.id.tv_spot);
		spot.setText(mLocation);
		OnInfoWindowClickListener listener = new OnInfoWindowClickListener() {
			public void onInfoWindowClick() {
				onClickInfoWindow(location);
			}
		};
		InfoWindow mInfoWindow = new InfoWindow(
				BitmapDescriptorFactory.fromView(view), location, -80, listener);

		mBaiduMap.showInfoWindow(mInfoWindow);
	}

	@Override
	public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
		if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
			return;
		}
		mBaiduMap.clear();
		mBaiduMap.addOverlay(new MarkerOptions().position(result.getLocation())
				.icon(BitmapDescriptorFactory
						.fromResource(R.drawable.icon_gcoding)));
		mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(result
				.getLocation()));
	}

	@Override
	public void onClick(View v) {

	}

	private void onClickInfoWindow(final LatLng location) {
		// 开启定位图层
		mBaiduMap.setMyLocationEnabled(true);
		// 定位初始化
		final LocationClient mLocClient = new LocationClient(
				EventLocationActivity.this);
		mLocClient.registerLocationListener(new BDLocationListener() {

			@Override
			public void onReceivePoi(BDLocation arg0) {

			}

			@Override
			public void onReceiveLocation(BDLocation arg0) {
				mLocClient.stop();
				LatLng start = new LatLng(arg0.getLatitude(), arg0
						.getLongitude());
				startNavi(start, location);
			}
		});
		LocationClientOption option = new LocationClientOption();
		option.setOpenGps(true);// 打开gps
		option.setCoorType("bd09ll"); // 设置坐标类型
		option.setScanSpan(1000);
		mLocClient.setLocOption(option);
		mLocClient.start();
	}

	/**
	 * 开始导航
	 * 
	 * @param view
	 */
	private void startNavi(LatLng pt1, LatLng pt2) {
		// 构建 导航参数
		NaviPara para = new NaviPara();
		para.startPoint = pt1;
		para.endPoint = pt2;
		try {
			BaiduMapNavigation.openBaiduMapNavi(para, this);
		} catch (BaiduMapAppNotSupportNaviException e) {
			AppContext.showToast("抱歉,你的百度地图暂不支持打开导航");
		}
	}

	@Override
	public void initView() {
		// 地图初始化
		mMapView = (MapView) findViewById(R.id.bmapView);
		mBaiduMap = mMapView.getMap();

		// 初始化搜索模块,注册事件监听
		mSearch = GeoCoder.newInstance();
		mSearch.setOnGetGeoCodeResultListener(this);

		Intent intent = getIntent();

		mCity = intent.getStringExtra("city");

		mLocation = intent.getStringExtra("location");

		// Geo搜索
		mSearch.geocode(new GeoCodeOption().city(mCity).address(mLocation));
	}

	@Override
	public void initData() {

	}
}

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.AppConfig;
import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.adapter.RecyclingPagerAdapter;
import net.oschina.app.base.BaseActivity;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.fragment.TweetPubFragment;
import net.oschina.app.ui.dialog.ImageMenuDialog;
import net.oschina.app.ui.dialog.ImageMenuDialog.OnMenuClickListener;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.UIHelper;
import net.oschina.app.widget.HackyViewPager;

import org.kymjs.kjframe.KJBitmap;
import org.kymjs.kjframe.bitmap.BitmapCallBack;

import uk.co.senab.photoview.PhotoView;
import uk.co.senab.photoview.PhotoViewAttacher.OnPhotoTapListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * 图片预览界面
 * 
 * @author kymjs
 */
public class ImagePreviewActivity extends BaseActivity implements
        OnPageChangeListener {

    public static final String BUNDLE_KEY_IMAGES = "bundle_key_images";
    private static final String BUNDLE_KEY_INDEX = "bundle_key_index";
    private HackyViewPager mViewPager;
    private SamplePagerAdapter mAdapter;
    private TextView mTvImgIndex;
    private ImageView mIvMore;
    private int mCurrentPostion = 0;
    private String[] mImageUrls;

    private KJBitmap kjb;

    public static void showImagePrivew(Context context, int index,
            String[] images) {
        Intent intent = new Intent(context, ImagePreviewActivity.class);

        intent.putExtra(BUNDLE_KEY_IMAGES, images);
        intent.putExtra(BUNDLE_KEY_INDEX, index);
        context.startActivity(intent);
    }

    @Override
    protected boolean hasActionBar() {
        getActionBar().hide();
        return true;
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_image_preview;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        super.init(savedInstanceState);
        kjb = new KJBitmap();
        mViewPager = (HackyViewPager) findViewById(R.id.view_pager);

        mImageUrls = getIntent().getStringArrayExtra(BUNDLE_KEY_IMAGES);
        int index = getIntent().getIntExtra(BUNDLE_KEY_INDEX, 0);

        mAdapter = new SamplePagerAdapter(mImageUrls);
        mViewPager.setAdapter(mAdapter);
        mViewPager.setOnPageChangeListener(this);
        mViewPager.setCurrentItem(index);

        mTvImgIndex = (TextView) findViewById(R.id.tv_img_index);
        mIvMore = (ImageView) findViewById(R.id.iv_more);
        mIvMore.setOnClickListener(this);

        onPageSelected(index);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
        case R.id.iv_more:
            showOptionMenu();
            break;
        default:
            break;
        }
    }

    @Override
    public void initView() {}

    @Override
    public void initData() {}

    private void showOptionMenu() {
        final ImageMenuDialog dialog = new ImageMenuDialog(this);
        dialog.show();
        dialog.setCancelable(true);
        dialog.setOnMenuClickListener(new OnMenuClickListener() {
            @Override
            public void onClick(TextView menuItem) {
                if (menuItem.getId() == R.id.menu1) {
                    saveImg();
                } else if (menuItem.getId() == R.id.menu2) {
                    sendTweet();
                } else if (menuItem.getId() == R.id.menu3) {
                    copyUrl();
                }
                dialog.dismiss();
            }
        });
    }

    /**
     * 复制链接
     */
    private void copyUrl() {
        String content = null;
        if (mAdapter != null && mAdapter.getCount() > 0) {
            content = mAdapter.getItem(mCurrentPostion);
            TDevice.copyTextToBoard(content);
            AppContext.showToastShort("已复制到剪贴板");
        }
    }

    /**
     * 发送到动弹
     */
    private void sendTweet() {
        if (mAdapter != null && mAdapter.getCount() > 0) {
            String imgUrl = mAdapter.getItem(mCurrentPostion);
            Bundle bundle = new Bundle();
            bundle.putString(TweetPubFragment.FROM_IMAGEPAGE_KEY, imgUrl);
            UIHelper.showSimpleBack(this, SimpleBackPage.TWEET_PUB, bundle);
            finish();
        }
    }

    /**
     * 保存图片
     */
    private void saveImg() {
        if (mAdapter != null && mAdapter.getCount() > 0) {
            final String imgUrl = mAdapter.getItem(mCurrentPostion);
            final String filePath = AppConfig.DEFAULT_SAVE_IMAGE_PATH
                    + getFileName(imgUrl);
            kjb.saveImage(this, imgUrl, filePath);
            AppContext.showToastShort(getString(R.string.tip_save_image_suc,
                    filePath));
        } else {
            AppContext.showToastShort(R.string.tip_save_image_faile);
        }
    }

    private String getFileName(String imgUrl) {
        int index = imgUrl.lastIndexOf('/') + 1;
        if (index == -1) {
            return System.currentTimeMillis() + ".jpeg";
        }
        return imgUrl.substring(index);
    }

    @Override
    public void onPageScrollStateChanged(int arg0) {}

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {}

    @Override
    public void onPageSelected(int idx) {
        mCurrentPostion = idx;
        if (mImageUrls != null && mImageUrls.length > 1) {
            if (mTvImgIndex != null) {
                mTvImgIndex.setText((mCurrentPostion + 1) + "/"
                        + mImageUrls.length);
            }
        }
    }

    class SamplePagerAdapter extends RecyclingPagerAdapter {

        private String[] images = new String[] {};

        SamplePagerAdapter(String[] images) {
            this.images = images;
        }

        public String getItem(int position) {
            return images[position];
        }

        @Override
        public int getCount() {
            return images.length;
        }

        @Override
        @SuppressLint("InflateParams")
        public View getView(int position, View convertView, ViewGroup container) {
            ViewHolder vh = null;
            if (convertView == null) {
                convertView = LayoutInflater.from(container.getContext())
                        .inflate(R.layout.image_preview_item, null);
                vh = new ViewHolder(convertView);
                convertView.setTag(vh);
            } else {
                vh = (ViewHolder) convertView.getTag();
            }
            vh.image.setOnFinishListener(new OnPhotoTapListener() {
                @Override
                public void onPhotoTap(View view, float x, float y) {
                    ImagePreviewActivity.this.finish();
                }
            });
            final ProgressBar bar = vh.progress;
            KJBitmap kjbitmap = new KJBitmap();
            kjbitmap.displayWithDefWH(vh.image, images[position],
                    new ColorDrawable(0x000000), new ColorDrawable(0x000000),
                    new BitmapCallBack() {
                        @Override
                        public void onPreLoad() {
                            super.onPreLoad();
                            bar.setVisibility(View.VISIBLE);
                        }

                        @Override
                        public void onFinish() {
                            super.onFinish();
                            bar.setVisibility(View.GONE);
                        }

                        @Override
                        public void onFailure(Exception arg0) {
                            AppContext.showToast(R.string.tip_load_image_faile);
                        }
                    });
            return convertView;
        }
    }

    static class ViewHolder {
        PhotoView image;
        ProgressBar progress;

        ViewHolder(View view) {
            image = (PhotoView) view.findViewById(R.id.photoview);
            progress = (ProgressBar) view.findViewById(R.id.progress);
        }
    }
}

 

 

 

 

 

 

 

package net.oschina.app.ui;

import java.io.ByteArrayInputStream;

import net.oschina.app.AppConfig;
import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.api.ApiHttpClient;
import net.oschina.app.api.remote.OSChinaApi;
import net.oschina.app.base.BaseActivity;
import net.oschina.app.bean.Constants;
import net.oschina.app.bean.LoginUserBean;
import net.oschina.app.bean.Result;
import net.oschina.app.util.CyptoUtils;
import net.oschina.app.util.SimpleTextWatcher;
import net.oschina.app.util.StringUtils;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.TLog;
import net.oschina.app.util.XmlUtils;

import org.apache.http.Header;
import org.apache.http.client.CookieStore;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.protocol.HttpContext;
import org.kymjs.kjframe.http.HttpConfig;
import org.kymjs.kjframe.utils.KJLoger;

import android.content.Intent;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import butterknife.InjectView;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;

/**
 * 用户登录界面
 * 
 * @author kymjs (http://www.kymjs.com/)
 */
public class LoginActivity extends BaseActivity {

    public static final int REQUEST_CODE_INIT = 0;
    private static final String BUNDLE_KEY_REQUEST_CODE = "BUNDLE_KEY_REQUEST_CODE";
    protected static final String TAG = LoginActivity.class.getSimpleName();

    @InjectView(R.id.et_username)
    EditText mEtUserName;

    @InjectView(R.id.et_password)
    EditText mEtPassword;

    @InjectView(R.id.iv_clear_username)
    View mIvClearUserName;

    @InjectView(R.id.iv_clear_password)
    View mIvClearPassword;

    @InjectView(R.id.btn_login)
    Button mBtnLogin;
    @InjectView(R.id.qq_login)
    Button mBtnQQLogin;

    private final int requestCode = REQUEST_CODE_INIT;
    private String mUserName;
    private String mPassword;

    private Tencent mTencent;

    private final TextWatcher mUserNameWatcher = new SimpleTextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            mIvClearUserName
                    .setVisibility(TextUtils.isEmpty(s) ? View.INVISIBLE
                            : View.VISIBLE);
        }
    };
    private final TextWatcher mPassswordWatcher = new SimpleTextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            mIvClearPassword
                    .setVisibility(TextUtils.isEmpty(s) ? View.INVISIBLE
                            : View.VISIBLE);
        }
    };

    @Override
    protected int getLayoutId() {
        return R.layout.activity_login;
    }

    @Override
    protected boolean hasBackButton() {
        return true;
    }

    @Override
    protected int getActionBarTitle() {
        return R.string.login;
    }

    @Override
    public void onClick(View v) {

        int id = v.getId();
        switch (id) {
        case R.id.iv_clear_username:
            mEtUserName.getText().clear();
            mEtUserName.requestFocus();
            break;
        case R.id.iv_clear_password:
            mEtPassword.getText().clear();
            mEtPassword.requestFocus();
            break;
        case R.id.btn_login:
            handleLogin();
            break;
        case R.id.qq_login:
            qqLogin();
            break;
        default:
            break;
        }
    }

    private void handleLogin() {

        if (!prepareForLogin()) {
            return;
        }

        // if the data has ready
        mUserName = mEtUserName.getText().toString();
        mPassword = mEtPassword.getText().toString();

        showWaitDialog(R.string.progress_login);
        OSChinaApi.login(mUserName, mPassword, mHandler);
    }

    private final AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            try {
                AsyncHttpClient client = ApiHttpClient.getHttpClient();
                HttpContext httpContext = client.getHttpContext();
                CookieStore cookies = (CookieStore) httpContext
                        .getAttribute(ClientContext.COOKIE_STORE);
                if (cookies != null) {
                    String tmpcookies = "";
                    for (Cookie c : cookies.getCookies()) {
                        TLog.log(TAG,
                                "cookie:" + c.getName() + " " + c.getValue());
                        tmpcookies += (c.getName() + "=" + c.getValue()) + ";";
                    }
                    TLog.log(TAG, "cookies:" + tmpcookies);
                    AppContext.getInstance().setProperty(AppConfig.CONF_COOKIE,
                            tmpcookies);
                    ApiHttpClient.setCookie(ApiHttpClient.getCookie(AppContext
                            .getInstance()));
                    HttpConfig.sCookie = tmpcookies;
                }
                LoginUserBean user = XmlUtils.toBean(LoginUserBean.class,
                        new ByteArrayInputStream(arg2));
                Result res = user.getResult();
                if (res.OK()) {
                    // 保存登录信息
                    user.getUser().setAccount(mUserName);
                    user.getUser().setPwd(mPassword);
                    user.getUser().setRememberMe(true);
                    AppContext.getInstance().saveUserInfo(user.getUser());
                    hideWaitDialog();
                    handleLoginSuccess();
                } else {
                    AppContext.getInstance().cleanLoginInfo();
                    hideWaitDialog();
                    AppContext.showToast(res.getErrorMessage());
                }
            } catch (Exception e) {
                e.printStackTrace();
                onFailure(arg0, arg1, arg2, e);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            hideWaitDialog();
            AppContext.showToast(R.string.tip_login_error_for_network);
        }
    };

    private void handleLoginSuccess() {
        Intent data = new Intent();
        data.putExtra(BUNDLE_KEY_REQUEST_CODE, requestCode);
        setResult(RESULT_OK, data);
        this.sendBroadcast(new Intent(Constants.INTENT_ACTION_USER_CHANGE));
        finish();
    }

    private boolean prepareForLogin() {
        if (!TDevice.hasInternet()) {
            AppContext.showToastShort(R.string.tip_no_internet);
            return false;
        }
        String uName = mEtUserName.getText().toString();
        if (StringUtils.isEmpty(uName)) {
            AppContext.showToastShort(R.string.tip_please_input_username);
            mEtUserName.requestFocus();
            return false;
        }
        // 去除邮箱正确性检测
        // if (!StringUtils.isEmail(uName)) {
        // AppContext.showToastShort(R.string.tip_illegal_email);
        // mEtUserName.requestFocus();
        // return false;
        // }
        String pwd = mEtPassword.getText().toString();
        if (StringUtils.isEmpty(pwd)) {
            AppContext.showToastShort(R.string.tip_please_input_password);
            mEtPassword.requestFocus();
            return false;
        }
        return true;
    }

    @Override
    public void initView() {
        mIvClearUserName.setOnClickListener(this);
        mIvClearPassword.setOnClickListener(this);
        mBtnLogin.setOnClickListener(this);
        mBtnQQLogin.setOnClickListener(this);

        mEtUserName.addTextChangedListener(mUserNameWatcher);
        mEtPassword.addTextChangedListener(mPassswordWatcher);
    }

    @Override
    public void initData() {
        mTencent = Tencent.createInstance(AppConfig.APP_QQ_KEY,
                this.getApplicationContext());

        mEtUserName.setText(AppContext.getInstance()
                .getProperty("user.account"));
        mEtPassword.setText(CyptoUtils.decode("oschinaApp", AppContext
                .getInstance().getProperty("user.pwd")));
    }

    /**
     * QQ登陆
     */
    private void qqLogin() {
        if (!mTencent.isSessionValid()) {
            mTencent.login(this, "all", new AuthorListener());
        }
    }

    // /**
    // * 封装并返回QQ登陆数据
    // */
    // private User packQQLoginBean(User user, JSONObject obj) {
    // user.setLoginType(QQ_LOGIN);
    // if (obj.has("openid")) {
    // user.setUserId(obj.optString("openid"));
    // } else {
    // user.setUserName(obj.optString("nickname"));
    // user.setSex("男".equals(obj.optString("gender")) ? 1 : 2);
    // user.setHeadUrl(obj.optString("figureurl_qq_1"));
    // user.setPwd(user.getUserId());
    // }
    // return user;
    // }

    class AuthorListener implements IUiListener {

        @Override
        public void onCancel() {
            KJLoger.debug(getClass().getName() + "用户取消登陆");
        }

        @Override
        public void onComplete(Object arg0) {
            // packQQLoginBean(user, obj);
            AppContext.showToast("成功"); // 服务器端暂无
        }

        @Override
        public void onError(UiError error) {
            KJLoger.debug(getClass().getName() + "登陆失败" + error.errorDetail);
        }
    }
}

 

 

 

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.AppContext;
import net.oschina.app.R;
import net.oschina.app.util.QrCodeUtils;

import org.kymjs.kjframe.utils.FileUtils;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.Window;
import android.widget.ImageView;

import com.google.zxing.WriterException;

public class MyQrodeDialog extends Dialog {

    private ImageView mIvCode;
    private Bitmap bitmap;

    private MyQrodeDialog(Context context, boolean flag,
            OnCancelListener listener) {
        super(context, flag, listener);
    }

    @SuppressLint("InflateParams")
    private MyQrodeDialog(Context context, int defStyle) {
        super(context, defStyle);
        View contentView = getLayoutInflater().inflate(
                R.layout.dialog_my_qr_code, null);
        mIvCode = (ImageView) contentView.findViewById(R.id.iv_qr_code);
        try {
            bitmap = QrCodeUtils.Create2DCode(String.format(
                    "http://my.oschina.net/u/%s", AppContext.getInstance()
                            .getLoginUid()));
            mIvCode.setImageBitmap(bitmap);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        contentView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                dismiss();
                if (FileUtils.bitmapToFile(bitmap,
                        FileUtils.getSavePath("OSChina") + "/myqrcode.png")) {
                    AppContext.showToast("二维码已保存到oschina文件夹下");
                } else {
                    AppContext.showToast("SD卡不可写,二维码保存失败");
                }
                return false;
            }
        });
        super.setContentView(contentView);
    }

    public MyQrodeDialog(Context context) {
        this(context, R.style.quick_option_dialog);
    }

    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        getWindow().setGravity(Gravity.CENTER);
    }
}

 

 

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.AppManager;
import net.oschina.app.R;
import net.oschina.app.base.BaseFragment;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.UIHelper;
import net.oschina.app.widget.ActionBarDrawerToggle;
import net.oschina.app.widget.DrawerArrowDrawable;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import butterknife.ButterKnife;
import butterknife.InjectView;

/**
 * 侧滑菜单界面
 * 
 * @author FireAnt(http://my.oschina.net/LittleDY)
 * @created 2014年9月25日 下午6:00:05
 * 
 */
public class NavigationDrawerFragment extends BaseFragment implements
	OnClickListener {

    /**
     * Remember the position of the selected item.
     */
    private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";

    /**
     * A pointer to the current callbacks instance (the Activity).
     */
    private NavigationDrawerCallbacks mCallbacks;

    /**
     * Helper component that ties the action bar to the navigation drawer.
     */
    private ActionBarDrawerToggle mDrawerToggle;

    private DrawerArrowDrawable drawerArrow;

    private DrawerLayout mDrawerLayout;
    private View mDrawerListView;
    private View mFragmentContainerView;

    private int mCurrentSelectedPosition = 0;
    private boolean mFromSavedInstanceState;

    @InjectView(R.id.menu_item_quests)
    View mMenu_item_quests;

    @InjectView(R.id.menu_item_opensoft)
    View mMenu_item_opensoft;

    @InjectView(R.id.menu_item_blog)
    View mMenu_item_blog;

    @InjectView(R.id.menu_item_gitapp)
    View mMenu_item_gitapp;

    @InjectView(R.id.menu_item_rss)
    View mMenu_item_rss;

    @InjectView(R.id.menu_item_setting)
    View mMenu_item_setting;

    @InjectView(R.id.menu_item_exit)
    View mMenu_item_exit;

    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);

	if (savedInstanceState != null) {
	    mCurrentSelectedPosition = savedInstanceState
		    .getInt(STATE_SELECTED_POSITION);
	    mFromSavedInstanceState = true;
	}

	selectItem(mCurrentSelectedPosition);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
	super.onActivityCreated(savedInstanceState);
	setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
	    Bundle savedInstanceState) {
	mDrawerListView = inflater.inflate(R.layout.fragment_navigation_drawer,
		container, false);
	mDrawerListView.setOnClickListener(this);
	ButterKnife.inject(this, mDrawerListView);
	initView(mDrawerListView);
	initData();
	return mDrawerListView;
    }

    @Override
    public void onClick(View v) {
	int id = v.getId();
	switch (id) {
	case R.id.menu_item_quests:
	    UIHelper.showSimpleBack(getActivity(), SimpleBackPage.QUEST);
	    break;
	case R.id.menu_item_opensoft:
	    UIHelper.showSimpleBack(getActivity(),
		    SimpleBackPage.OPENSOURCE_SOFTWARE);
	    break;
	case R.id.menu_item_blog:
	    UIHelper.showSimpleBack(getActivity(), SimpleBackPage.BLOG);
	    break;
	case R.id.menu_item_gitapp:

	    boolean res = TDevice.openAppActivity(getActivity(),
		    "net.oschina.gitapp", "net.oschina.gitapp.WelcomePage");

	    if (!res) {
		if (!TDevice.isHaveMarket(getActivity())) {
		    UIHelper.openSysBrowser(getActivity(),
			    "http://git.oschina.net/appclient");
		} else {
		    TDevice.gotoMarket(getActivity(), "net.oschina.gitapp");
		}
	    }

	    break;
	case R.id.menu_item_rss:
	    break;
	case R.id.menu_item_setting:
	    UIHelper.showSetting(getActivity());
	    break;
	case R.id.menu_item_exit:
	    AppManager.getAppManager().AppExit(getActivity());
	    break;
	default:
	    break;

	}
	mDrawerLayout.postDelayed(new Runnable() {

	    @Override
	    public void run() {
		mDrawerLayout.closeDrawers();
	    }
	}, 800);
    }

    @Override
    public void initView(View view) {

	mMenu_item_rss.setOnClickListener(this);
	mMenu_item_opensoft.setOnClickListener(this);
	mMenu_item_blog.setOnClickListener(this);
	mMenu_item_quests.setOnClickListener(this);

	mMenu_item_setting.setOnClickListener(this);
	mMenu_item_exit.setOnClickListener(this);

	mMenu_item_gitapp.setOnClickListener(this);
    }

    @Override
    public void initData() {
    }

    public boolean isDrawerOpen() {
	return mDrawerLayout != null
		&& mDrawerLayout.isDrawerOpen(mFragmentContainerView);
    }

    /**
     * Users of this fragment must call this method to set up the navigation
     * drawer interactions.
     * 
     * @param fragmentId
     *            The android:id of this fragment in its activity's layout.
     * @param drawerLayout
     *            The DrawerLayout containing this fragment's UI.
     */
    public void setUp(int fragmentId, DrawerLayout drawerLayout) {
	mFragmentContainerView = getActivity().findViewById(fragmentId);
	mDrawerLayout = drawerLayout;

	// set a custom shadow that overlays the main content when the drawer
	// opens
	mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
		GravityCompat.START);
	// set up the drawer's list view with items and click listener

	ActionBar actionBar = getActionBar();
	actionBar.setDisplayHomeAsUpEnabled(true);
	actionBar.setHomeButtonEnabled(true);

	drawerArrow = new DrawerArrowDrawable(getActivity()) {
	    @Override
	    public boolean isLayoutRtl() {
		return false;
	    }
	};

	mDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout,
		drawerArrow, R.string.navigation_drawer_open,
		R.string.navigation_drawer_close) {

	    public void onDrawerClosed(View view) {
		super.onDrawerClosed(view);
		getActivity().invalidateOptionsMenu();
	    }

	    public void onDrawerOpened(View drawerView) {
		super.onDrawerOpened(drawerView);
		getActivity().invalidateOptionsMenu();
	    }
	};

	mDrawerLayout.post(new Runnable() {
	    @Override
	    public void run() {
		mDrawerToggle.syncState();
	    }
	});

	mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    public void openDrawerMenu() {
	mDrawerLayout.openDrawer(mFragmentContainerView);
    }

    private void selectItem(int position) {
	mCurrentSelectedPosition = position;
	if (mDrawerLayout != null) {
	    mDrawerLayout.closeDrawer(mFragmentContainerView);
	}
	if (mCallbacks != null) {
	    mCallbacks.onNavigationDrawerItemSelected(position);
	}
    }

    @Override
    public void onAttach(Activity activity) {
	super.onAttach(activity);
	try {
	    mCallbacks = (NavigationDrawerCallbacks) activity;
	} catch (ClassCastException e) {
	    throw new ClassCastException(
		    "Activity must implement NavigationDrawerCallbacks.");
	}
    }

    @Override
    public void onDetach() {
	super.onDetach();
	mCallbacks = null;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
	super.onConfigurationChanged(newConfig);
	mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
	super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
	if (mDrawerToggle.onOptionsItemSelected(item)) {
	    return true;
	}

	return super.onOptionsItemSelected(item);
    }

    private ActionBar getActionBar() {
	return ((ActionBarActivity) getActivity()).getSupportActionBar();
    }

    public static interface NavigationDrawerCallbacks {
	void onNavigationDrawerItemSelected(int position);
    }
}

 

 

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.fragment.TweetPubFragment;
import net.oschina.app.team.fragment.NoteEditFragment;
import net.oschina.app.util.UIHelper;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;

public class QuickOptionDialog extends Dialog implements
        android.view.View.OnClickListener {

    private ImageView mClose;

    public interface OnQuickOptionformClick {
        void onQuickOptionClick(int id);
    }

    private OnQuickOptionformClick mListener;

    private QuickOptionDialog(Context context, boolean flag,
            OnCancelListener listener) {
        super(context, flag, listener);
    }

    @SuppressLint("InflateParams")
    private QuickOptionDialog(Context context, int defStyle) {
        super(context, defStyle);
        View contentView = getLayoutInflater().inflate(
                R.layout.dialog_quick_option, null);
        contentView.findViewById(R.id.ly_quick_option_text).setOnClickListener(
                this);
        contentView.findViewById(R.id.ly_quick_option_album)
                .setOnClickListener(this);
        contentView.findViewById(R.id.ly_quick_option_photo)
                .setOnClickListener(this);
        contentView.findViewById(R.id.ly_quick_option_voice)
                .setOnClickListener(this);
        contentView.findViewById(R.id.ly_quick_option_scan).setOnClickListener(
                this);
        contentView.findViewById(R.id.ly_quick_option_note).setOnClickListener(
                this);
        mClose = (ImageView) contentView.findViewById(R.id.iv_close);

        Animation operatingAnim = AnimationUtils.loadAnimation(getContext(),
                R.anim.quick_option_close);
        LinearInterpolator lin = new LinearInterpolator();
        operatingAnim.setInterpolator(lin);

        mClose.startAnimation(operatingAnim);

        mClose.setOnClickListener(this);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        contentView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                QuickOptionDialog.this.dismiss();
                return true;
            }
        });
        super.setContentView(contentView);

    }

    public QuickOptionDialog(Context context) {
        this(context, R.style.quick_option_dialog);
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        getWindow().setGravity(Gravity.BOTTOM);

        WindowManager m = getWindow().getWindowManager();
        Display d = m.getDefaultDisplay();
        WindowManager.LayoutParams p = getWindow().getAttributes();
        p.width = d.getWidth();
        getWindow().setAttributes(p);
    }

    public void setOnQuickOptionformClickListener(OnQuickOptionformClick lis) {
        mListener = lis;
    }

    @Override
    public void onClick(View v) {
        final int id = v.getId();
        switch (id) {
        case R.id.iv_close:
            dismiss();
            break;
        case R.id.ly_quick_option_text:
            onClickTweetPub(R.id.ly_quick_option_text);
            break;
        case R.id.ly_quick_option_album:
            onClickTweetPub(R.id.ly_quick_option_album);
            break;
        case R.id.ly_quick_option_photo:
            onClickTweetPub(R.id.ly_quick_option_photo);
            break;
        case R.id.ly_quick_option_voice:
            UIHelper.showSimpleBack(getContext(), SimpleBackPage.RECORD);
            break;
        case R.id.ly_quick_option_scan:
            UIHelper.showScanActivity(getContext());
            break;
        case R.id.ly_quick_option_note:
            // UIHelper.showSimpleBack(getContext(), SimpleBackPage.FIND_USER);
            onClickNote();
            //UIHelper.showSimpleBack(getContext(), SimpleBackPage.FIND_USER);
            // onClickNote();
            break;
        default:
            break;
        }
        if (mListener != null) {
            mListener.onQuickOptionClick(id);
        }
        dismiss();
    }

    private void onClickTweetPub(int id) {
        Bundle bundle = new Bundle();
        int type = -1;
        switch (id) {
        case R.id.ly_quick_option_album:
            type = TweetPubFragment.ACTION_TYPE_ALBUM;
            break;
        case R.id.ly_quick_option_photo:
            type = TweetPubFragment.ACTION_TYPE_PHOTO;
            break;
        default:
            break;
        }
        bundle.putInt(TweetPubFragment.ACTION_TYPE, type);
        UIHelper.showTweetActivity(getContext(), SimpleBackPage.TWEET_PUB,
                bundle);
    }

    private void onClickNote() {
        Bundle bundle = new Bundle();
        bundle.putInt(NoteEditFragment.NOTE_FROMWHERE_KEY,
                NoteEditFragment.QUICK_DIALOG);
        UIHelper.showSimpleBack(getContext(), SimpleBackPage.NOTE_EDIT, bundle);
    }
}

 

 

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.bean.Report;
import net.oschina.app.ui.dialog.CommonDialog;
import net.oschina.app.ui.dialog.DialogHelper;
import net.oschina.app.util.TDevice;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.TextView;

public class ReportDialog extends CommonDialog implements
		android.view.View.OnClickListener {

	private static final int MAX_CONTENT_LENGTH = 250;
	private TextView mTvReason;
	private TextView mTvLink;
	private EditText mEtContent;
	private String[] reasons;
	private String mLink;
	private int mReportId;

	public ReportDialog(Context context, String link, int reportId) {
		this(context, R.style.dialog_common, link, reportId);
	}

	private ReportDialog(Context context, int defStyle, String link,
			int reportId) {
		super(context, defStyle);
		mLink = link;
		mReportId = reportId;
		initViews(context);
	}

	private ReportDialog(Context context, boolean flag,
			OnCancelListener listener) {
		super(context, flag, listener);
	}

	@SuppressLint("InflateParams")
	private void initViews(Context context) {
		reasons = getContext().getResources().getStringArray(
				R.array.report_reason);

		View view = getLayoutInflater()
				.inflate(R.layout.dialog_report, null);

		mTvReason = (TextView) view.findViewById(R.id.tv_reason);
		mTvReason.setOnClickListener(this);

		mTvReason.setText(reasons[0]);

		mTvLink = (TextView) view.findViewById(R.id.tv_link);
		mTvLink.setText(mLink);

		mEtContent = (EditText) view.findViewById(R.id.et_content);
		
		super.setContent(view, 0);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.tv_reason) {
			selectReason();
		}
	}

	private void selectReason() {
		String reason = mTvReason.getText().toString();
		int idx = 0;
		for (int i = 0; i < reasons.length; i++) {
			if (reasons[i].equals(reason)) {
				idx = i;
				break;
			}
		}
		final CommonDialog dialog = DialogHelper
				.getPinterestDialogCancelable(getContext());
		dialog.setTitle(R.string.report_reson);
		dialog.setItems(reasons, idx, new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				dialog.dismiss();
				mTvReason.setText(reasons[position]);
			}
		});
		dialog.setNegativeButton(R.string.cancle, null);
		dialog.show();
	}

	public Report getReport() {
		String text = mEtContent.getText().toString();
		TDevice.hideSoftKeyboard(mEtContent);
		Report report = new Report();
		report.setReportId(mReportId);
		report.setLinkAddress(mLink);
		report.setReason(mTvReason.getText().toString());
		report.setOtherReason(text);
		return report;
	}
}

 

 

 

 

 

 

package net.oschina.app.ui;

import net.oschina.app.R;
import net.oschina.app.ui.dialog.CommonDialog;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;

/**
 * 分享界面dialog
 * 
 * @author kymjs
 * 
 */
public class ShareDialog extends CommonDialog implements
        android.view.View.OnClickListener {

    public interface OnSharePlatformClick {
        void onPlatformClick(int id);
    }

    private OnSharePlatformClick mListener;

    private ShareDialog(Context context, boolean flag, OnCancelListener listener) {
        super(context, flag, listener);
    }

    @SuppressLint("InflateParams")
    private ShareDialog(Context context, int defStyle) {
        super(context, defStyle);
        View shareView = getLayoutInflater().inflate(
                R.layout.dialog_cotent_share, null);
        shareView.findViewById(R.id.ly_share_qq).setOnClickListener(this);
        shareView.findViewById(R.id.ly_share_copy_link)
                .setOnClickListener(this);
        shareView.findViewById(R.id.ly_share_more_option).setOnClickListener(
                this);
        shareView.findViewById(R.id.ly_share_sina_weibo).setOnClickListener(
                this);
        shareView.findViewById(R.id.ly_share_weichat).setOnClickListener(this);
        shareView.findViewById(R.id.ly_share_weichat_circle)
                .setOnClickListener(this);
        setContent(shareView, 0);
    }

    public ShareDialog(Context context) {
        this(context, R.style.dialog_bottom);
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        getWindow().setGravity(Gravity.BOTTOM);

        WindowManager m = getWindow().getWindowManager();
        Display d = m.getDefaultDisplay();
        WindowManager.LayoutParams p = getWindow().getAttributes();
        p.width = d.getWidth();
        getWindow().setAttributes(p);
    }

    public void setOnPlatformClickListener(OnSharePlatformClick lis) {
        mListener = lis;
    }

    @Override
    public void onClick(View v) {
        final int id = v.getId();
        if (mListener != null) {
            mListener.onPlatformClick(id);
        }
    }
}

 

 

 

 

 

 

 

 

package net.oschina.app.ui;

import java.util.ArrayList;

import net.oschina.app.bean.SimpleBackPage;
import net.oschina.app.fragment.TweetPubFragment;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;

/**
 * 对动弹界面的一个封装,用于相应系统分享
 * 
 * @author kymjs (https://github.com/kymjs)
 * 
 */
public class TweetActivity extends SimpleBackActivity {
    private TweetPubFragment currentFragment;

    public static String FROM_KEY = "image_shared_key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Intent intent = getIntent();
        if (intent.getIntExtra(FROM_KEY, -1) != 1) {
            mPageValue = SimpleBackPage.TWEET_PUB.getValue();
        }
        super.onCreate(savedInstanceState);
        respondExternal(intent);
    }

    /**
     * 响应从图片分享进入的事件
     * 
     * @param intent
     */
    private void respondExternal(Intent intent) {
        currentFragment = (TweetPubFragment) mFragment.get();

        String action = intent.getAction();
        String type = intent.getType();

        if (Intent.ACTION_SEND.equals(action) && type != null) {
            if ("text/plain".equals(type)) {
                handleSendText(intent); // Handle text being sent
            } else if (type.startsWith("image/")) {
                handleSendImage(intent); // Handle single image being sent
            }
        } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
            if (type.startsWith("image/")) {
                handleSendMultipleImages(intent); // Handle multiple images
                                                  // being sent
            }
        } else {
            // Handle other intents, such as being started from the home screen
        }
    }

    void handleSendText(Intent intent) {
        String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
        String sharedTitle = intent.getStringExtra(Intent.EXTRA_TITLE);
        if (sharedText != null) {
            currentFragment.setContentText(sharedText);
        }
    }

    void handleSendImage(Intent intent) {
        Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
        if (imageUri != null) {
            currentFragment.setContentImage(getAbsoluteImagePath(imageUri));
        }
    }

    void handleSendMultipleImages(Intent intent) {
        ArrayList<Uri> imageUris = intent
                .getParcelableArrayListExtra(Intent.EXTRA_STREAM);
        if (imageUris != null) {
            currentFragment.setContentImage(getAbsoluteImagePath(imageUris
                    .get(0)));
        }
    }

    protected String getAbsoluteImagePath(Uri uri) {
        // can post image
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, proj, // Which columns to return
                null, // WHERE clause; which rows to return (all rows)
                null, // WHERE clause selection arguments (none)
                null); // Order-by clause (ascending by name)
        if (cursor != null) {
            int column_index = cursor
                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();

            return cursor.getString(column_index);
        } else {
            // 如果游标为空说明获取的已经是绝对路径了
            return uri.getPath();
        }
    }
}

 

 

 

 

 

 

 

package net.oschina.app.ui.dialog;

import net.oschina.app.R;
import net.oschina.app.util.TDevice;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;

public class CommonDialog extends Dialog {
	public DialogInterface.OnClickListener listener;
	protected View barDivider;
	protected View buttonDivider;
	protected FrameLayout container;
	protected View content;
	private final int contentPadding;

	protected DialogTitleView headerVw;
	protected Button negativeBt;
	protected Button positiveBt;
	protected DialogInterface.OnClickListener dismissClick = new OnClickListener() {

		@Override
		public void onClick(DialogInterface dialog, int which) {
			dialog.dismiss();
		}
	};

	public CommonDialog(Context context) {
		this(context, R.style.dialog_common);
	}

	public CommonDialog(Context context, int defStyle) {
		super(context, defStyle);
		contentPadding = (int) getContext().getResources().getDimension(
				R.dimen.global_dialog_padding);
		init(context);
	}

	protected CommonDialog(Context context, boolean flag,
			DialogInterface.OnCancelListener listener) {
		super(context, flag, listener);
		contentPadding = (int) getContext().getResources().getDimension(
				R.dimen.global_dialog_padding);
		init(context);
	}

	@SuppressLint("InflateParams")
	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	protected void init(final Context context) {
		setCancelable(false);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		content = LayoutInflater.from(context).inflate(
				R.layout.dialog_common, null);
		headerVw = (DialogTitleView) content.findViewById(R.id.dialog_header);
		container = (FrameLayout) content.findViewById(R.id.content_container);
		barDivider = content.findViewById(R.id.button_bar_divider);
		buttonDivider = content.findViewById(R.id.button_divder);
		positiveBt = (Button) content.findViewById(R.id.positive_bt);
		negativeBt = (Button) content.findViewById(R.id.negative_bt);
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
			// TODO Check content view height and change height

		} else {
//			content.addOnLayoutChangeListener(new OnLayoutChangeListener() {
//
//				@Override
//				public void onLayoutChange(View v, int left, int top,
//						int right, int bottom, int oldLeft, int oldTop,
//						int oldRight, int oldBottom) {
//					int height = v.getHeight();
//					int contentHeight = container.getHeight();
//					int winHeight = BaseApplication.getDisplaySize()[1];
//					int needHeight = height - winHeight * 8 / 10;
//					if (needHeight > 0) {
//						container
//								.setLayoutParams(new LinearLayout.LayoutParams(
//										LayoutParams.MATCH_PARENT,
//										contentHeight - needHeight));
//					}
//				}
//			});
		}
		super.setContentView(content);
	}

	public TextView getTitleTextView() {
		return headerVw.titleTv;
	}

	@Override
	protected void onCreate(Bundle bundle) {
		super.onCreate(bundle);
		if (TDevice.isTablet()) {
			int maxWidth = (int) TDevice.dpToPixel(360f);
			if (maxWidth < TDevice.getScreenWidth()) {
				WindowManager.LayoutParams params = getWindow().getAttributes();
				params.width = maxWidth;
				getWindow().setAttributes(params);
			}
		}
	}
	
	

	@Override
	public void onBackPressed() {
		super.onBackPressed();
		this.dismiss();
	}

	public void setContent(View view) {
		setContent(view, contentPadding);
	}

	public void setContent(View view, int padding) {
		container.removeAllViews();
		container.setPadding(padding, padding, padding, padding);
		FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
				FrameLayout.LayoutParams.MATCH_PARENT,
				FrameLayout.LayoutParams.MATCH_PARENT);
		container.addView(view, lp);
	}

	@Override
	public void setContentView(int i) {
		setContent(null);
	}

	@Override
	public void setContentView(View view) {
		setContentView(null, null);
	}

	@Override
	public void setContentView(View view,
			android.view.ViewGroup.LayoutParams layoutparams) {
		throw new Error("Dialog: User setContent (View view) instead!");
	}

	public void setItems(BaseAdapter adapter,
			AdapterView.OnItemClickListener onItemClickListener) {
		ListView listview = new ListView(content.getContext());
		listview.setLayoutParams(new FrameLayout.LayoutParams(-1, -2));
		listview.setDivider(null);
		listview.setAdapter(adapter);
		listview.setOnItemClickListener(onItemClickListener);
		setContent(listview, 0);
	}

	public void setItems(CharSequence[] items,
			AdapterView.OnItemClickListener onItemClickListener) {
		ListView listview = new ListView(content.getContext());
		listview.setLayoutParams(new FrameLayout.LayoutParams(-1, -2));
		listview.setAdapter(new DialogAdapter(items));
		listview.setDivider(null);
		listview.setOnItemClickListener(onItemClickListener);
		setContent(listview, 0);
	}

	public void setItemsWithoutChk(CharSequence[] items,
			AdapterView.OnItemClickListener onItemClickListener) {
		ListView listview = new ListView(content.getContext());
		listview.setLayoutParams(new FrameLayout.LayoutParams(-1, -2));
		DialogAdapter adapter = new DialogAdapter(items);
		adapter.setShowChk(false);
		listview.setDivider(null);
		listview.setAdapter(adapter);
		listview.setOnItemClickListener(onItemClickListener);
		setContent(listview, 0);
	}

	public void setItems(CharSequence[] items, int index,
			AdapterView.OnItemClickListener onItemClickListener) {
		ListView listview = new ListView(content.getContext());
		listview.setCacheColorHint(0);
		listview.setDivider(null);
		listview.setLayoutParams(new FrameLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
		listview.setAdapter(new DialogAdapter(items, index));
		listview.setOnItemClickListener(onItemClickListener);
		setContent(listview, 0);
	}

	public void setMessage(int resId) {
		setMessage(getContext().getResources().getString(resId));
	}

	public void setMessage(Spanned spanned) {
		ScrollView scrollView = new ScrollView(getContext());
		scrollView.setLayoutParams(new FrameLayout.LayoutParams(
				FrameLayout.LayoutParams.MATCH_PARENT,
				FrameLayout.LayoutParams.WRAP_CONTENT));
		TextView tvMessage = new TextView(getContext(), null,
				R.style.dialog_pinterest_text);
		tvMessage.setLayoutParams(new FrameLayout.LayoutParams(
				FrameLayout.LayoutParams.MATCH_PARENT,
				FrameLayout.LayoutParams.WRAP_CONTENT));
		tvMessage.setPadding(contentPadding, contentPadding, contentPadding,
				contentPadding);
		tvMessage.setLineSpacing(0.0F, 1.3F);
		tvMessage.setText(spanned);
		tvMessage.setTextColor(getContext().getResources().getColor(
				R.color.black));

		ScrollView.LayoutParams lp = new ScrollView.LayoutParams(
				ScrollView.LayoutParams.MATCH_PARENT,
				ScrollView.LayoutParams.WRAP_CONTENT);
		scrollView.addView(tvMessage, lp);
		setContent(scrollView, 0);
	}

	public void setMessage(String message) {
		setMessage(Html.fromHtml(message));
	}

	public void setNegativeButton(int negative,
			DialogInterface.OnClickListener listener) {
		setNegativeButton(getContext().getString(negative), listener);
	}

	public void setNegativeButton(String text,
			final DialogInterface.OnClickListener listener) {
		if (!TextUtils.isEmpty(text)) {
			negativeBt.setText(text);
			negativeBt.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View view) {
					if (listener != null)
						listener.onClick(CommonDialog.this, 0);
					else
						dismissClick.onClick(CommonDialog.this, 0);
				}
			});
			negativeBt.setVisibility(View.VISIBLE);
			if (positiveBt.getVisibility() == View.VISIBLE)
				buttonDivider.setVisibility(View.VISIBLE);
		} else {
			negativeBt.setVisibility(View.GONE);
			buttonDivider.setVisibility(View.GONE);
		}
		if (positiveBt.getVisibility() == View.VISIBLE
				|| negativeBt.getVisibility() == View.VISIBLE)
			barDivider.setVisibility(View.VISIBLE);
		else
			barDivider.setVisibility(View.GONE);
	}

	public void setPositiveButton(int positive,
			DialogInterface.OnClickListener listener) {
		setPositiveButton(getContext().getString(positive), listener);
	}

	public void setPositiveButton(String positive,
			final DialogInterface.OnClickListener listener) {
		if (!TextUtils.isEmpty(positive)) {
			positiveBt.setText(positive);
			positiveBt.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View view) {
					if (listener != null)
						listener.onClick(CommonDialog.this, 0);
					else
						dismissClick.onClick(CommonDialog.this, 0);
				}
			});
			positiveBt.setVisibility(View.VISIBLE);
			if (negativeBt.getVisibility() == View.VISIBLE)
				buttonDivider.setVisibility(View.VISIBLE);
		} else {
			positiveBt.setVisibility(View.GONE);
			buttonDivider.setVisibility(View.GONE);
		}
		if (positiveBt.getVisibility() == View.VISIBLE
				|| negativeBt.getVisibility() == View.VISIBLE)
			barDivider.setVisibility(View.VISIBLE);
		else
			barDivider.setVisibility(View.GONE);
	}

	public void setSubTitle(int i) {
		setSubTitle((getContext().getResources().getString(i)));
	}

	public void setSubTitle(CharSequence subtitle) {
		if (subtitle != null && subtitle.length() > 0) {
			headerVw.subTitleTv.setText(subtitle);
			headerVw.subTitleTv.setVisibility(View.VISIBLE);
		} else {
			headerVw.subTitleTv.setVisibility(View.GONE);
		}
	}

	@Override
	public void setTitle(int title) {
		setTitle((getContext().getResources().getString(title)));
	}

	@Override
	public void setTitle(CharSequence title) {
		if (title != null && title.length() > 0) {
			headerVw.titleTv.setText(title);
			headerVw.setVisibility(View.VISIBLE);
		} else {
			headerVw.setVisibility(View.GONE);
		}
	}
}

 

 

 

 

 

 

package net.oschina.app.ui.dialog;

import net.oschina.app.R;
import net.oschina.app.util.TDevice;
import net.oschina.app.util.TLog;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class CommonToast {
	public static final long DURATION_LONG = 5000L;
	public static final long DURATION_MEDIUM = 3500L;
	public static final long DURATION_SHORT = 2500L;
	private long _duration = 3500l;
	private ToastView _toastVw;

	public CommonToast(Activity activity) {
		init(activity);
	}

	public CommonToast(Activity activity, String message, int icon,
			String action, int actionIcon, long l) {
		_duration = l;
		init(activity);
		setMessage(message);
		setMessageIc(icon);
		setAction(action);
		setActionIc(actionIcon);
	}

	private void init(Activity activity) {
		_toastVw = new ToastView(activity);
		setLayoutGravity(81);
	}

	public long getDuration() {
		return _duration;
	}

	public void setAction(String s) {
		_toastVw.actionTv.setText(s);
	}

	public void setActionIc(int i) {
		_toastVw.actionIv.setImageResource(i);
	}

	public void setDuration(long l) {
		_duration = l;
	}

	public void setLayoutGravity(int i) {
		if (i != 0) {
			FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2,
					-2);
			params.gravity = i;
			int j = (int) TDevice.dpToPixel(16F);
			params.setMargins(j, j, j, j);
			_toastVw.setLayoutParams(params);
		}
	}

	public void setMessage(String s) {
		_toastVw.messageTv.setText(s);
	}

	public void setMessageIc(int i) {
		_toastVw.messageIc.setImageResource(i);
	}

	public void show() {
		final ViewGroup content = (ViewGroup) ((Activity) _toastVw.getContext())
				.findViewById(android.R.id.content);
		if (content != null) {
			ObjectAnimator.ofFloat(_toastVw, "alpha", 0.0F).setDuration(0L)
					.start();
			content.addView(_toastVw);
			ObjectAnimator.ofFloat(_toastVw, "alpha", 0.0F, 1.0F)
					.setDuration(167L).start();
			_toastVw.postDelayed(new Runnable() {

				@Override
				public void run() {
					ObjectAnimator animator = ObjectAnimator.ofFloat(_toastVw,
							"alpha", 1.0F, 0.0F);
					animator.setDuration(100L);
					animator.addListener(new AnimatorListener() {

						@Override
						public void onAnimationStart(Animator animation) {
							// TODO Auto-generated method stub
						}

						@Override
						public void onAnimationRepeat(Animator animation) {
							// TODO Auto-generated method stub
						}

						@Override
						public void onAnimationEnd(Animator animation) {
							content.removeView(_toastVw);
						}

						@Override
						public void onAnimationCancel(Animator animation) {

						}
					});
					animator.start();
				}
			}, _duration);
		} else {
			TLog.error("Toast not shown! Content view is null!");
		}
	}

	private class ToastView extends FrameLayout {

		public ImageView actionIv;
		public TextView actionTv;
		public ImageView messageIc;
		public TextView messageTv;

		public ToastView(Context context) {
			this(context, null);
		}

		public ToastView(Context context, AttributeSet attributeset) {
			this(context, attributeset, 0);
		}

		public ToastView(Context context, AttributeSet attributeset, int i) {
			super(context, attributeset, i);
			init();
		}

		private void init() {
			LayoutInflater.from(getContext()).inflate(
					R.layout.view_base_toast, this, true);
			messageTv = (TextView) findViewById(R.id.title_tv);
			messageIc = (ImageView) findViewById(R.id.icon_iv);
			actionTv = (TextView) findViewById(R.id.title_tv);
			actionIv = (ImageView) findViewById(R.id.icon_iv);
		}
	}
}

 

 

 

 

 

 

 

package net.oschina.app.ui.dialog;

import net.oschina.app.R;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RadioButton;
import android.widget.TextView;

public class DialogAdapter extends BaseAdapter {

	private CharSequence[] _items;
	private int select;
	private boolean showChk = true;
	
	public DialogAdapter(CharSequence[] items, int selectIdx) {
		_items = items;
		this.select = selectIdx;
	}
	
	public DialogAdapter(CharSequence[] items) {
		_items = items;
	}

	@Override
	public int getCount() {
		return _items.length;
	}

	@Override
	public String getItem(int i) {
		return _items[i].toString();// super.getItem(i);
	}

	@Override
	public long getItemId(int i) {
		return i;
	}

	@Override
	public View getView(int i, View view, ViewGroup viewgroup) {
		DialogHolder vh = null;
		if (view == null) {
			vh = new DialogHolder();
			view = LayoutInflater.from(viewgroup.getContext()).inflate(
					R.layout.list_cell_dialog, null, false);
			vh.titleTv = (TextView) view.findViewById(R.id.title_tv);
			vh.divider = view.findViewById(R.id.list_divider);
			vh.checkIv = (RadioButton) view.findViewById(R.id.rb_select);
			view.setTag(vh);
		} else {
			vh = (DialogHolder) view.getTag();
		}
		vh.titleTv.setText(getItem(i));
		
		if (i == -1 + getCount()) {
			vh.divider.setVisibility(View.GONE);
		} else {
			vh.divider.setVisibility(View.VISIBLE);
		}
		
		if(showChk) {
			vh.checkIv.setVisibility(View.VISIBLE);
			if (select == i) {
				vh.checkIv.setChecked(true);
			} else {
				vh.checkIv.setChecked(false);
			}
		} else{
			vh.checkIv.setVisibility(View.GONE);
		}
		return view;
	}

	public boolean isShowChk() {
		return showChk;
	}

	public void setShowChk(boolean showChk) {
		this.showChk = showChk;
	}

	private class DialogHolder {
		public View divider;
		public TextView titleTv;
		public RadioButton checkIv;
	}
}

 

 

 

 

 

package net.oschina.app.ui.dialog;

public interface DialogControl {

	public abstract void hideWaitDialog();

	public abstract WaitDialog showWaitDialog();

	public abstract WaitDialog showWaitDialog(int resid);

	public abstract WaitDialog showWaitDialog(String text);
}

 

 

 

 

 

package net.oschina.app.ui.dialog;

import net.oschina.app.R;
import android.app.Activity;
import android.content.Context;

public class DialogHelper {
	
	public static CommonDialog getPinterestDialog(Context context) {
		return new CommonDialog(context, R.style.dialog_common);
	}

	public static CommonDialog getPinterestDialogCancelable(Context context) {
		CommonDialog dialog = new CommonDialog(context,
				R.style.dialog_common);
		dialog.setCanceledOnTouchOutside(true);
		return dialog;
	}

	public static WaitDialog getWaitDialog(Activity activity, int message) {
		WaitDialog dialog = null;
		try {
			dialog = new WaitDialog(activity, R.style.dialog_waiting);
			dialog.setMessage(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dialog;
	}

	public static WaitDialog getWaitDialog(Activity activity, String message) {
		WaitDialog dialog = null;
		try {
			dialog = new WaitDialog(activity, R.style.dialog_waiting);
			dialog.setMessage(message);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return dialog;
	}

	public static WaitDialog getCancelableWaitDialog(Activity activity,
			String message) {
		WaitDialog dialog = null;
		try {
			dialog = new WaitDialog(activity, R.style.dialog_waiting);
			dialog.setMessage(message);
			dialog.setCancelable(true);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return dialog;
	}

}

 

 

 

 

 

 

package net.oschina.app.ui.dialog;

import net.oschina.app.R;
import net.oschina.app.util.TDevice;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

public class WaitDialog extends Dialog {

	private TextView _messageTv;
	
	public WaitDialog(Context context) {
		super(context);
		init(context);
	}

	public WaitDialog(Context context, int defStyle) {
		super(context, defStyle);
		init(context);
	}

	protected WaitDialog(Context context, boolean cancelable,DialogInterface.OnCancelListener listener) {
		super(context, cancelable, listener);
		init(context);
	}

	public static boolean dismiss(WaitDialog dialog) {
		if (dialog != null) {
			dialog.dismiss();
			return false;
		} else {
			return true;
		}
	}
	
	@Override
	public void onBackPressed() {
		super.onBackPressed();
		this.dismiss();
	}

	public static void hide(Context context) {
		if (context instanceof DialogControl)
			((DialogControl) context).hideWaitDialog();
	}

	public static boolean hide(WaitDialog dialog) {
		if (dialog != null) {
			dialog.hide();
			return false;
		} else {
			return true;
		}
	}

	private void init(Context context) {
		setCancelable(false);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		View view = LayoutInflater.from(context).inflate(R.layout.dialog_wait, null);
		_messageTv = (TextView) view.findViewById(R.id.waiting_tv);
		setContentView(view);
	}

	public static void show(Context context) {
		if (context instanceof DialogControl)
			((DialogControl) context).showWaitDialog();
	}

	public static boolean show(WaitDialog waitdialog) {
		boolean flag;
		if (waitdialog != null) {
			waitdialog.show();
			flag = false;
		} else {
			flag = true;
		}
		return flag;
	}

	@Override
	protected void onCreate(Bundle bundle) {
		super.onCreate(bundle);
		if (TDevice.isTablet()) {
			int i = (int) TDevice.dpToPixel(360F);
			if (i < TDevice.getScreenWidth()) {
				WindowManager.LayoutParams params = getWindow()
						.getAttributes();
				params.width = i;
				getWindow().setAttributes(params);
			}
		}
	}

	public void setMessage(int message) {
		_messageTv.setText(message);
	}

	public void setMessage(String message) {
		_messageTv.setText(message);
	}
	
	public void hideMessage() {
	    _messageTv.setVisibility(View.GONE);
	}
}

 

 

分享到:
评论

相关推荐

    oschina-app 最新源码

    【oschina-app】是中国开源社区OSChina.net...通过研究oschina-app的源码,开发者可以学习到如何在Android平台上构建一个功能完备的应用,同时掌握各种最佳实践和技术,这对于提升个人技能和解决实际问题非常有帮助。

    OSChina Android客户端源码

    通过深入学习和分析OSChina Android客户端的源码,你不仅能掌握Android开发的基本技巧,还能了解到一些高级特性和最佳实践,对于提升自己的Android开发能力大有裨益。在实际操作中,你可以模仿并运用这些知识到自己...

    oschina android 客户端源码

    【oschina android 客户端源码】是一个公开的项目,旨在为开发者提供一个学习和研究Android应用开发的优秀实例。这个源码库包含了OSChina.net Android客户端的完整源代码,展示了一个成熟、功能完善的移动应用是如何...

    oschina android app

    【描述】"oschina android app code" 指的是该应用的源码,对于开发者而言,这是一个学习和研究Android应用开发的宝贵资源。通过分析源码,开发者可以深入理解如何在Android平台上构建一个完整的社交网络应用,包括...

    android oschina-android-app源码.rar

    【Android OSChina-Android-App源码分析】 这个压缩包文件"android oschina-android-app源码.rar"包含的是OSChina Android应用的源代码,OSChina是中国知名的开源技术社区,其官方Android应用集成了最新的开源技术...

    OSChina Android 客户端源码

    【标题】"OSChina Android 客户端源码"揭示了这是一个开源项目,专注于为OSChina网站构建Android应用的客户端程序。OSChina是中国最大的开源技术社区,提供最新的开源资讯、项目托管服务以及丰富的技术交流平台。这...

    oschina的android客户端源码

    【oschina的Android客户端源码】是一份针对中国开源社区OSChina.net的移动应用的源代码,主要面向Android操作系统。这份源代码对于开发者而言是一份宝贵的资源,它提供了深入理解Android应用开发、学习最佳实践以及...

    oschina-android-app(开源中国)

    总的来说,"oschina-android-app(开源中国)"是一个全面展示Android应用开发的实例,通过对源码的研究,开发者不仅可以掌握Android开发的基本技能,还能了解到实际项目中的最佳实践,对个人能力提升大有裨益。

    Android应用源码之oschina-android-app(开源中国).zip

    【Android应用源码之oschina-android-app(开源中国)】是一个专门为Android开发者提供的学习资源,它包含了开源中国官方Android应用程序的源代码。这个项目对于深入理解Android应用开发、熟悉开源中国的功能实现...

    Android源码——oschina-android-app(开源中国).zip

    【Android源码——oschina-android-app(开源中国)】是一个包含开源中国Android应用程序的源代码压缩包。这个项目是开源的,允许开发者深入研究和学习Android应用开发的实践技巧和最佳实践。通过分析这个项目的源...

    安卓Android源码——oschina--app.zip

    《安卓Android源码解析——oschina-app》 在移动开发领域,Android系统因其开源特性而备受开发者喜爱。本文将深入探讨“oschina-android-app”这一特定的安卓应用源码,帮助开发者理解其背后的架构设计、功能实现...

    oschina的android端的源码

    首先,我们要明确的是,"oschina"是知名的中文开源技术平台,其Android客户端旨在为用户提供便捷的开源资讯浏览、项目管理和讨论交流等功能。源码的开放,让我们得以窥见一个成熟应用的内部运作机制。 在源码中,...

    Android应用源码之oschina-android-app(开源中国)-IT计算机-毕业设计.zip

    【Android应用源码之oschina-android-app(开源中国)】是一个专门为IT计算机专业学生和开发者提供的毕业设计资源,它包含了开源中国(OSChina)的Android应用程序的源代码。这个项目对于那些想要深入理解Android...

    oschina开源中国Android源码v2.71

    oschina开源中国Android源码v2.71

    oschina-android-app(开源中国).rar

    本篇将详细介绍“oschina-android-app”这一开源项目的相关知识点。 一、Android应用开发基础 在Android平台上开发应用,首先需要掌握Java或Kotlin编程语言。开源中国Android应用是用Java编写的,因此对Java基础有...

    安卓Android源码——oschina-android-app(开源中国).zip

    "安卓Android源码——oschina-android-app(开源中国).zip" 这个标题表明我们讨论的是一个关于安卓应用的源代码,具体是开源中国的Android客户端应用的源码。开源中国是一个知名的社区,专注于分享和交流开源技术,...

    oschina-android-app

    "oschina-android-app"是一个专为开源中国(oschina.net)设计和开发的Android手机客户端应用。这个项目展示了如何将一个在线社区的众多功能适配到移动设备上,为用户提供便捷的开源技术资讯、代码分享、博客阅读以及...

Global site tag (gtag.js) - Google Analytics