Android搭建本地服務(wù)器卫旱,實現(xiàn)視頻加密

需求:下載視頻人灼,下載后只能用自己的APP打開,不允許傳播

實現(xiàn)思路:服務(wù)器加密顾翼,下載下來本地解密投放,由于android播放視頻需要解密完成后再播放,這樣存在安全問題适贸,所以我就搭建本地服務(wù)器灸芳,實現(xiàn)視頻加密

1.先給出build的內(nèi)容,搭建本地服務(wù)器拜姿,我使用的是AndroidAsync開源庫實現(xiàn)

compile 'com.koushikdutta.async:androidasync:2.+'

2.話不多說烙样,直接上代碼,由于是demo蕊肥,加密和解密都是本地實現(xiàn)

public class MainActivityextends AppCompatActivityimplements View.OnClickListener, NIOHttpServer.ExistenceListener {

private static final StringTAG ="MainActivity";

    private VideoViewmVideoView;

    private ButtonmButton1, mButton2;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        init();

        mButton1.setOnClickListener(this);

        mButton2.setOnClickListener(this);

        //本地服務(wù)器啟動

        new Thread(new Runnable() {

@Override

            public void run() {//開一個線程防止卡住ui線程

                NIOHttpServer

.getInstance(MainActivity.this)

.startServer(MainActivity.this);//本地服務(wù)器開始啟動谒获,傳入監(jiān)聽,監(jiān)聽文件是否存在

            }

}).start();

    }

private void init() {

mVideoView = findViewById(R.id.mVideoView);

        mButton1 = findViewById(R.id.mButton1);

        mButton2 = findViewById(R.id.mButton2);

    }

@Override

    public void onClick(View v) {

int id = v.getId();

        switch (id) {

case R.id.mButton1://加密

                try {

//獲取assets目錄下面的文件流

                    InputStream inputStream = getResources().getAssets().open("test.mp4", AssetManager.ACCESS_RANDOM);

                    File file =new File(Environment.getExternalStorageDirectory().getPath() +"/out.zc");//加密后的文件的路徑

                    BufferedOutputStream out =new BufferedOutputStream(new FileOutputStream(file));

                    byte[] bytes1 ="qwertyuiopa".getBytes();

                    //開頭寫入11個干擾字符 寫入后視頻打不開

                    out.write(bytes1);

                    byte[] bytes =new byte[512];

                    int l;

                    //正常的寫入視頻源文件呢

                    while ((l = inputStream.read(bytes, 0, bytes.length)) != -1) {

out.write(bytes, 0, l);

                    }

inputStream.close();

                    out.close();

                    Log.e(TAG, "onClick: 完成了加密");

                    Toast.makeText(MainActivity.this, "完成了加密", Toast.LENGTH_SHORT).show();

                }catch (IOException e) {

e.printStackTrace();

                }

break;

            case R.id.mButton2://播放

                test2();

break;

        }

}

private void test2() {

String code = UnicodeUtils.string2Unicode("out.zc");

        Uri uri = Uri.parse("http://127.0.0.1:5000/" + code);//后面的參數(shù)必須進行Unicode編碼壁却,防止中文亂碼

//設(shè)置視頻控制器

        MediaController controller =new MediaController(this);

        mVideoView.setMediaController(controller);

        //播放完成回調(diào)

        mVideoView.setOnCompletionListener(new MyPlayerOnCompletionListener());

        //設(shè)置視頻路徑

        mVideoView.setVideoURI(uri);

        //開始播放視頻

        mVideoView.start();

        mVideoView.requestFocus();

    }

@Override

    public void fail(String str) {//文件不存在

        //todo

    }

@Override

    public void success() {//成功

        //todo

    }

class MyPlayerOnCompletionListenerimplements MediaPlayer.OnCompletionListener {

@Override

        public void onCompletion(MediaPlayer mp) {

}

}

}

3.本地服務(wù)器端的實現(xiàn)

public class NIOHttpServerimplements HttpServerRequestCallback {

private static final StringTAG ="NIOHttpServer";

    //當(dāng)前類的實列 采用用單列

    private static NIOHttpServermInstance;

    //端口

    public static int PORT_LISTEN_DEFALT =5000;

    //監(jiān)聽

    private ExistenceListenerexistenceListener;

    //服務(wù)器實列

    private AsyncHttpServerserver =new AsyncHttpServer();

    //單列模式

    public static NIOHttpServergetInstance(Context context1) {

if (mInstance ==null) {//懶漢的寫法

// 增加類鎖,保證只初始化一次

            synchronized (NIOHttpServer.class) {

if (mInstance ==null) {

mInstance =new NIOHttpServer();

                }

}

}

return mInstance;

    }

//返回錯誤碼枚舉

    public static enum Status {

REQUEST_OK(200, "請求成功"),

        REQUEST_ERROR(500, "請求失敗"),

        REQUEST_ERROR_API(501, "無效的請求接口"),

        REQUEST_ERROR_CMD(502, "無效命令"),

        REQUEST_ERROR_DEVICEID(503, "不匹配的設(shè)備ID"),

        REQUEST_ERROR_ENV(504, "不匹配的服務(wù)環(huán)境");

        private final int requestStatus;

        private final Stringdescription;

        Status(int requestStatus, String description) {

this.requestStatus = requestStatus;

            this.description = description;

        }

public StringgetDescription() {

return description;

        }

public int getRequestStatus() {

return requestStatus;

        }

}

/**

* 開啟本地服務(wù)

*/

    public void startServer(ExistenceListener existenceListener) {

//如果有其他的請求方式批狱,例如下面一行代碼的寫法

        server.addAction("OPTIONS", "[\\d\\D]*", this);

        server.get("[\\d\\D]*", this);

        server.post("[\\d\\D]*", this);

        //服務(wù)器監(jiān)聽端口

        server.listen(PORT_LISTEN_DEFALT);

        //傳入監(jiān)聽進來

        this.existenceListener = existenceListener;

    }

@Override

    public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {

//unicode轉(zhuǎn)換

        String unicode = request.getPath().replace("/", "\\");

        //獲取傳入的參數(shù)

        String param = UnicodeUtils.unicode2String(unicode);

        Log.d(TAG, "onRequest: " + param +"  " + unicode);

        //這個是獲取header參數(shù)的地方,一定要謹(jǐn)記

        Multimap headers = request.getHeaders().getMultiMap();

        // 獲取本地的存文件的目錄

        String path = Environment.getExternalStorageDirectory().getPath();

        //獲取文件路徑

        String filePath = path +"/" + param; // 根據(jù)url獲取文件路徑

        if (TextUtils.isEmpty(path)) {

response.send("sd卡沒有找到");

return;

        }

File file =new File(filePath);

        BufferedInputStream stream =null;

        FileInputStream inputStream =null;

        try {

if (file !=null && file.exists()) {

existenceListener.success();//存在文件

                Log.d(TAG, "file path = " + file.getAbsolutePath());

                //獲取本地文件的輸入流

                inputStream =new FileInputStream(file);

                //干擾字符 “qwertyuiopa”一共有11位

                byte[] bytes =new byte[11];

                //不要開頭寫入的字符

                inputStream.read(bytes, 0, bytes.length);

                //寫入的干擾字符

                Log.d(TAG, "onRequest: " +new String(bytes));

                //出去干擾字符的流

                stream =new BufferedInputStream(inputStream);

                //寫出沒有干擾字符的流

                response.sendStream(stream, stream.available());

            }else {

Log.d(TAG, "file path = " + file.getAbsolutePath() +"的資源不存在");

                existenceListener.fail("資源不存在");//不存在文件

            }

}catch (IOException e) {

e.printStackTrace();

        }

}

interface ExistenceListener {

void fail(String str);

        void success();

    }

}```
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末展东,一起剝皮案震驚了整個濱河市赔硫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盐肃,老刑警劉巖卦停,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異恼蓬,居然都是意外死亡惊完,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門处硬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來小槐,“玉大人,你說我怎么就攤上這事≡涮” “怎么了件豌?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長控嗜。 經(jīng)常有香客問我茧彤,道長,這世上最難降的妖魔是什么疆栏? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任曾掂,我火速辦了婚禮,結(jié)果婚禮上壁顶,老公的妹妹穿的比我還像新娘珠洗。我一直安慰自己,他們只是感情好若专,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布七扰。 她就那樣靜靜地躺著吱窝,像睡著了一般隅忿。 火紅的嫁衣襯著肌膚如雪入客。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天嚎莉,我揣著相機與錄音蚁飒,去河邊找鬼。 笑死萝喘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的琼懊。 我是一名探鬼主播阁簸,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哼丈!你這毒婦竟也來了启妹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤醉旦,失蹤者是張志新(化名)和其女友劉穎饶米,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體车胡,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡檬输,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了匈棘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丧慈。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出逃默,到底是詐尸還是另有隱情鹃愤,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布完域,位于F島的核電站软吐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吟税。R本人自食惡果不足惜凹耙,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乌妙。 院中可真熱鬧使兔,春花似錦、人聲如沸藤韵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泽艘。三九已至欲险,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匹涮,已是汗流浹背天试。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留然低,地道東北人喜每。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像雳攘,于是被迫代替她去往敵國和親带兜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容